From 47a40b9b6112d6fb5eb111cb8dba339ac880d7b8 Mon Sep 17 00:00:00 2001 From: Austin Fatheree Date: Tue, 25 Mar 2025 10:20:19 -0500 Subject: [PATCH] Adding conversion with result types --- CHANGELOG.md | 6 + mops.toml | 3 +- src/conversion copy.mo | 2096 ++++++++++++++++++++++++++++ src/icrc16/conversion.mo | 2638 +++++++++++++++++++++++++++++++++++ test/bool_to_bytes.test.mo | 21 + test/bytes_to_bool.test.mo | 35 + test/conversion.test.mo | 2672 ++++++++++++++++++++++++++++++++++++ 7 files changed, 7470 insertions(+), 1 deletion(-) create mode 100644 src/conversion copy.mo create mode 100644 src/icrc16/conversion.mo create mode 100644 test/bool_to_bytes.test.mo create mode 100644 test/bytes_to_bool.test.mo create mode 100644 test/conversion.test.mo diff --git a/CHANGELOG.md b/CHANGELOG.md index ac0355d..7eab3e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +v0.3.1 + +- Added the /icrc16 folder and the conversions.mo file there to begin conversion to icrc16 reference. +- Conversions in /icrc16/conversion.mo generally return result types and should not throw. +- Added tests for /icrc16/conversion.mo + v0.3.0 - Added the ValueShared type for dumping a Candy and CandyShared to an ICRC3 style Value type. diff --git a/mops.toml b/mops.toml index 7d3050c..2f8f7d9 100644 --- a/mops.toml +++ b/mops.toml @@ -11,10 +11,11 @@ candy_0_1_12 = "https://github.com/icdevs/candy_library#v0.1.12@20db7a8a74258bb0 candy_0_2_0 = "https://github.com/icdevs/candy_library#0.2.0@4fc5aebec44355da94a4d3ebef87623e4545d89a" encoding_0_4_1 = "https://github.com/aviate-labs/encoding.mo#v0.4.1@2711d18727e954b11afc0d37945608512b5fbce2" vector = "0.2.0" +principal-ext = "0.1.0" [package] name = "candy" -version = "0.3.0" +version = "0.3.1" description = "Library for Converting Types and Creating Workable Motoko Collections" repository = "https://github.com/icdevs/candy_library" diff --git a/src/conversion copy.mo b/src/conversion copy.mo new file mode 100644 index 0000000..5f3655e --- /dev/null +++ b/src/conversion copy.mo @@ -0,0 +1,2096 @@ +/////////////////////////////// +// +// ©2021 @aramakme +// +//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +//The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////// + +/// Conversion utilities for the candy library. +/// +/// This module contains the conversion functions to convert values to & from +/// candy values. + +import Buffer "mo:base/Buffer"; +import Blob "mo:base/Blob"; +import Char "mo:base/Char"; +import Iter "mo:base/Iter"; +import Text "mo:base/Text"; +import HashMap "mo:base/HashMap"; +import Array "mo:base/Array"; +import Nat "mo:base/Nat"; +import Nat16 "mo:base/Nat16"; +import Nat32 "mo:base/Nat32"; +import Nat64 "mo:base/Nat64"; +import Nat8 "mo:base/Nat8"; +import Float "mo:base/Float"; +import Int "mo:base/Int"; +import Int8 "mo:base/Int8"; +import Int16 "mo:base/Int16"; +import Int32 "mo:base/Int32"; +import Int64 "mo:base/Int64"; +import Bool "mo:base/Bool"; +import Principal "mo:base/Principal"; +import Prelude "mo:base/Prelude"; +import List "mo:base/List"; +import Types "types"; +import Hex "mo:encoding_0_4_1/Hex"; +import Properties "properties"; +import StableBuffer "mo:stablebuffer_1_3_0/StableBuffer"; +import Map "mo:map9/Map"; +import Set "mo:map9/Set"; + + +module { + + type CandyShared = Types.CandyShared; + type Candy = Types.Candy; + type ValueShared = Types.ValueShared; + type DataZone = Types.DataZone; + type PropertyShared = Types.PropertyShared; + type Property = Types.Property; + type StableBuffer = StableBuffer.StableBuffer; + + //todo: generic accesors + + /// Convert a `Candy` to `Nat`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int16(15); + /// let converted_value = Conversion.candyToNat(value); + /// ``` + /// Note: Throws if the underlying value overflows or is negative. + public func candyToNat(val : Candy) : Nat { + switch(val){ + case(#Nat(val)){ val}; + case(#Nat8(val)){ Nat8.toNat(val)}; + case(#Nat16(val)){ Nat16.toNat(val)}; + case(#Nat32(val)){ Nat32.toNat(val)}; + case(#Nat64(val)){ Nat64.toNat(val)}; + case(#Float(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){assert false;};//will throw on negative + + Int.abs(val)}; + case(#Int8(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat(#Int(Int8.toInt(Int8.abs(val))))};//will throw on overflow + case(#Int16(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat(#Int(Int16.toInt(Int16.abs(val))))};//will throw on overflow + case(#Int32(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat(#Int(Int32.toInt(Int32.abs(val))))};//will throw on overflow + case(#Int64(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat(#Int(Int64.toInt(Int64.abs(val))))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `Candy` to `Nat8`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToNat8(value); + /// ``` + /// Note: Throws if the underlying value overflows or is negative. + public func candyToNat8(val : Candy) : Nat8 { + switch(val){ + case(#Nat8(val)){ val}; + case(#Nat(val)){ Nat8.fromNat(val)};//will throw on overflow + case(#Nat16(val)){ Nat8.fromNat(Nat16.toNat(val))};//will throw on overflow + case(#Nat32(val)){ Nat8.fromNat(Nat32.toNat(val))};//will throw on overflow + case(#Nat64(val)){ Nat8.fromNat(Nat64.toNat(val))};//will throw on overflow + case(#Float(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat8(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat8(#Nat(Int.abs(val)))}; + case(#Int8(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat8(#Int(Int8.toInt(Int8.abs(val))))};//will throw on overflow + case(#Int16(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat8(#Int(Int16.toInt(Int16.abs(val))))};//will throw on overflow + case(#Int32(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat8(#Int(Int32.toInt(Int32.abs(val))))};//will throw on overflow + case(#Int64(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat8(#Int(Int64.toInt(Int64.abs(val))))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `Candy` to `Nat16`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToNat16(value); + /// ``` + /// Note: Throws if the underlying value overflows or is negative. + public func candyToNat16(val : Candy) : Nat16 { + switch(val){ + case(#Nat16(val)){ val}; + case(#Nat8(val)){Nat16.fromNat(Nat8.toNat(val))}; + case(#Nat(val)){Nat16.fromNat(val)};//will throw on overflow + case(#Nat32(val)){Nat16.fromNat(Nat32.toNat(val))};//will throw on overflow + case(#Nat64(val)){Nat16.fromNat(Nat64.toNat(val))};//will throw on overflow + case(#Float(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat16(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat16(#Nat(Int.abs(val)))}; + case(#Int8(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat16(#Int(Int8.toInt(Int8.abs(val))))};//will throw on overflow + case(#Int16(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat16(#Int(Int16.toInt(Int16.abs(val))))};//will throw on overflow + case(#Int32(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat16(#Int(Int32.toInt(Int32.abs(val))))};//will throw on overflow + case(#Int64(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat16(#Int(Int64.toInt(Int64.abs(val))))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `Candy` to `Nat32`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToNat32(value); + /// ``` + /// Note: Throws if the underlying value overflows or is negative. + public func candyToNat32(val : Candy) : Nat32 { + switch(val){ + case(#Nat32(val)){ val}; + case(#Nat16(val)){ Nat32.fromNat(Nat16.toNat(val))}; + case(#Nat8(val)){ Nat32.fromNat(Nat8.toNat(val))}; + case(#Nat(val)){ Nat32.fromNat(val)};//will throw on overflow + case(#Float(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat32(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat32(#Nat(Int.abs(val)))}; + case(#Int8(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat32(#Int(Int8.toInt(Int8.abs(val))))};//will throw on overflow + case(#Int16(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat32(#Int(Int16.toInt(Int16.abs(val))))};//will throw on overflow + case(#Int32(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat32(#Int(Int32.toInt(Int32.abs(val))))};//will throw on overflow + case(#Int64(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat32(#Int(Int64.toInt(Int64.abs(val))))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `Candy` to `Nat64`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToNat64(value); + /// ``` + /// Note: Throws if the underlying value overflows or is negative. + public func candyToNat64(val : Candy) : Nat64 { + switch(val){ + case(#Nat64(val)){ val}; + case(#Nat32(val)){ Nat64.fromNat(Nat32.toNat(val))}; + case(#Nat16(val)){ Nat64.fromNat(Nat16.toNat(val))}; + case(#Nat8(val)){ Nat64.fromNat(Nat8.toNat(val))}; + case(#Nat(val)){ Nat64.fromNat(val)}; + case(#Float(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat64(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat64(#Nat(Int.abs(val)))}; + case(#Int8(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat64(#Int(Int8.toInt(Int8.abs(val))))};//will throw on overflow + case(#Int16(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat64(#Int(Int16.toInt(Int16.abs(val))))};//will throw on overflow + case(#Int32(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat64(#Int(Int32.toInt(Int32.abs(val))))};//will throw on overflow + case(#Int64(val)){ + if(val < 0){assert false;};//will throw on negative + candyToNat64(#Int(Int64.toInt(Int64.abs(val))))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `Candy` to `Int`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToInt(value); + /// ``` + /// Note: Throws if the underlying value overflows. + public func candyToInt(val : Candy) : Int { + switch(val){ + case(#Int(val)){ val}; + case(#Int8(val)){ Int8.toInt(val)}; + case(#Int16(val)){ Int16.toInt(val)}; + case(#Int32(val)){ Int32.toInt(val)}; + case(#Int64(val)){ Int64.toInt(val)}; + case(#Nat(val)){ val}; + case(#Nat8(val)){ Nat8.toNat(val)}; + case(#Nat16(val)){ Nat16.toNat(val)}; + case(#Nat32(val)){ Nat32.toNat(val)}; + case(#Nat64(val)){Nat64.toNat(val)}; + case(#Float(val)){ Float.toInt(Float.nearest(val))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `Candy` to `Int8`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToInt8(value); + /// ``` + /// Note: Throws if the underlying value overflows. + public func candyToInt8(val : Candy) : Int8 { + switch(val){ + case(#Int8(val)){val}; + case(#Int(val)){ Int8.fromInt(val)};//will throw on overflow + case(#Int16(val)){ Int8.fromInt(Int16.toInt(val))};//will throw on overflow + case(#Int32(val)){ Int8.fromInt(Int32.toInt(val))};//will throw on overflow + case(#Int64(val)){ Int8.fromInt(Int64.toInt(val))};//will throw on overflow + case(#Nat8(val)){ Int8.fromNat8(val)}; + case(#Nat(val)){Int8.fromNat8(candyToNat8(#Nat(val)))};//will throw on overflow + case(#Nat16(val)){Int8.fromNat8(candyToNat8(#Nat16(val)))};//will throw on overflow + case(#Nat32(val)){Int8.fromNat8(candyToNat8(#Nat32(val)))};//will throw on overflow + case(#Nat64(val)){Int8.fromNat8(candyToNat8(#Nat64(val)))};//will throw on overflow + case(#Float(val)){ Int8.fromInt(Float.toInt(Float.nearest(val)))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `Candy` to `Int16`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToInt16(value); + /// ``` + /// Note: Throws if the underlying value overflows. + public func candyToInt16(val : Candy) : Int16 { + switch(val){ + case(#Int16(val)){ val}; + case(#Int8(val)){ Int16.fromInt(Int8.toInt(val))}; + case(#Int(val)){ Int16.fromInt(val)};//will throw on overflow + case(#Int32(val)){ Int16.fromInt(Int32.toInt(val))};//will throw on overflow + case(#Int64(val)){ Int16.fromInt(Int64.toInt(val))};//will throw on overflow + case(#Nat8(val)){Int16.fromNat16(candyToNat16(#Nat8(val)))}; + case(#Nat(val)){Int16.fromNat16(candyToNat16(#Nat(val)))};//will throw on overflow + case(#Nat16(val)){ Int16.fromNat16(val)}; + case(#Nat32(val)){Int16.fromNat16(candyToNat16(#Nat32(val)))};//will throw on overflow + case(#Nat64(val)){Int16.fromNat16(candyToNat16(#Nat64(val)))};//will throw on overflow + case(#Float(val)){ Int16.fromInt(Float.toInt(Float.nearest(val)))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `Candy` to `Int32`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToInt32(value); + /// ``` + /// Note: Throws if the underlying value overflows. + public func candyToInt32(val : Candy) : Int32 { + switch(val){ + case(#Int32(val)){val}; + case(#Int16(val)){Int32.fromInt(Int16.toInt(val))}; + case(#Int8(val)){Int32.fromInt(Int8.toInt(val))}; + case(#Int(val)){Int32.fromInt(val)};//will throw on overflow + case(#Nat8(val)){Int32.fromNat32(candyToNat32(#Nat8(val)))}; + case(#Nat(val)){Int32.fromNat32(candyToNat32(#Nat(val)))};//will throw on overflow + case(#Nat16(val)){Int32.fromNat32(candyToNat32(#Nat16(val)))}; + case(#Nat32(val)){Int32.fromNat32(val)}; + case(#Nat64(val)){Int32.fromNat32(candyToNat32(#Nat64(val)))};//will throw on overflow + case(#Float(val)){Int32.fromInt(Float.toInt(Float.nearest(val)))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `Candy` to `Int64`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToInt64(value); + /// ``` + /// Note: Throws if the underlying value overflows. + public func candyToInt64(val : Candy) : Int64 { + switch(val){ + case(#Int64(val)){ val}; + case(#Int32(val)){ Int64.fromInt(Int32.toInt(val))}; + case(#Int16(val)){ Int64.fromInt(Int16.toInt(val))}; + case(#Int8(val)){ Int64.fromInt(Int8.toInt(val))}; + case(#Int(val)){ Int64.fromInt(val)};//will throw on overflow + case(#Nat8(val)){Int64.fromNat64(candyToNat64(#Nat8(val)))}; + case(#Nat(val)){Int64.fromNat64(candyToNat64(#Nat(val)))};//will throw on overflow + case(#Nat16(val)){Int64.fromNat64(candyToNat64(#Nat16(val)))}; + case(#Nat32(val)){Int64.fromNat64(candyToNat64(#Nat32(val)))};//will throw on overflow + case(#Nat64(val)){ Int64.fromNat64(val)}; + case(#Float(val)){ Float.toInt64(Float.nearest(val))}; + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `Candy` to `Float`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int16(2); + /// let converted_value = Conversion.candyToFloat(value); + /// ``` + /// Note: Throws if the underlying value overflows. + public func candyToFloat(val : Candy) : Float { + switch(val){ + case(#Float(val)){ val}; + case(#Int64(val)){ Float.fromInt64(val)}; + case(#Int32(val)){candyToFloat(#Int(Int32.toInt(val)))}; + case(#Int16(val)){candyToFloat(#Int(Int16.toInt(val)))}; + case(#Int8(val)){candyToFloat(#Int(Int8.toInt(val)))}; + case(#Int(val)){ Float.fromInt(val)}; + case(#Nat8(val)){candyToFloat(#Int(Nat8.toNat(val)))}; + case(#Nat(val)){candyToFloat(#Int(val))};//will throw on overflow + case(#Nat16(val)){candyToFloat(#Int(Nat16.toNat(val)))}; + case(#Nat32(val)){candyToFloat(#Int(Nat32.toNat(val)))};//will throw on overflow + case(#Nat64(val)){candyToFloat(#Int(Nat64.toNat(val)))}; + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `Candy` to `Text`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToText(value); + /// ``` + public func candyToText(val : Candy) : Text { + switch(val){ + case(#Text(val)){ val}; + case(#Nat64(val)){ Nat64.toText(val)}; + case(#Nat32(val)){ Nat32.toText(val)}; + case(#Nat16(val)){ Nat16.toText(val)}; + case(#Nat8(val)){ Nat8.toText(val)}; + case(#Nat(val)){ Nat.toText(val)}; + case(#Int64(val)){ Int64.toText(val)}; + case(#Int32(val)){ Int32.toText(val)}; + case(#Int16(val)){ Int16.toText(val)}; + case(#Int8(val)){ Int8.toText(val)}; + case(#Int(val)){ Int.toText(val)}; + case(#Bool(val)){ Bool.toText(val)}; + case(#Float(val)){ Float.format(#exact, val)}; + case(#Option(val)){ + switch(val){ + case(null){ "null"}; + case(?val){candyToText(val)}; + }; + }; + //blob + case(#Blob(val)){ + return Hex.encode(Blob.toArray(val)); + }; + //class + case(#Class(val)){ //this is currently not parseable and should probably just be used for debuging. It would be nice to output candid. + + var t = "{"; + for(thisItem in Map.entries(val)){ + t := t # thisItem.1.name # ":" # (if(thisItem.1.immutable == false){"var "}else{""}) # candyToText(thisItem.1.value) # "; "; + }; + + return Text.trimEnd(t, #text(" ")) # "}"; + + + }; + //principal + case(#Principal(val)){ Principal.toText(val)}; + //array + case(#Array(val)){ + + var t = "["; + for(thisItem in StableBuffer.vals(val)){ + t := t # "{" # candyToText(thisItem) # "} "; + }; + + return Text.trimEnd(t, #text(" ")) # "]"; + + }; + //floats + case(#Floats(val)){ + + var t = "["; + for(thisItem in StableBuffer.vals(val)){ + t := t # Float.format(#exact, thisItem) # " "; + }; + + return Text.trimEnd(t, #text(" ")) # "]"; + + }; + //floats + case(#Nats(val)){ + + var t = "["; + for(thisItem in StableBuffer.vals(val)){ + t := t # Nat.toText(thisItem) # " "; + }; + + return Text.trimEnd(t, #text(" ")) # "]"; + + }; + //floats + case(#Ints(val)){ + + var t = "["; + for(thisItem in StableBuffer.vals(val)){ + t := t # Int.toText(thisItem) # " "; + }; + + return Text.trimEnd(t, #text(" ")) # "]"; + + }; + //bytes + case(#Bytes(val)){ + + return Hex.encode(StableBuffer.toArray(val)); + + }; + case(#Set(val)){ //this is currently not parseable and should probably just be used for debuging. It would be nice to output candid. + + var t = "["; + for(thisItem in Set.keys(val)){ + t := t # "{" # candyToText(thisItem) # "} "; + }; + + return Text.trimEnd(t, #text(" ")) # "]"; + + + }; + case(#Map(val)){ //this is currently not parseable and should probably just be used for debuging. It would be nice to output candid. + + var t = "{"; + for(thisItem in Map.entries(val)){ + t := t # thisItem.0 # ":" # candyToText(thisItem.1) # "; "; + }; + + return Text.trimEnd(t, #text(" ")) # "}"; + + + }; + case(#ValueMap(val)){ //this is currently not parseable and should probably just be used for debuging. It would be nice to output candid. + + var t = "{"; + for(thisItem in Map.entries(val)){ + t := t # candyToText(thisItem.0) # ":" # candyToText(thisItem.1) # "; "; + }; + + return Text.trimEnd(t, #text(" ")) # "}"; + + + }; + //case(_){assert(false);/*unreachable*/"";}; + }; + }; + + /// Convert a `Candy` to `Principal`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Principal(Principal.fromText("abc")); + /// let converted_value = Conversion.candyToPrincipal(value); + /// ``` + /// Note: Throws if the underlying value is not a `#Principal`. + public func candyToPrincipal(val : Candy) : Principal { + switch(val){ + case(#Principal(val)){val}; + case(_){assert(false);/*unreachable*/Principal.fromText("");}; + }; + }; + + /// Convert a `Candy` to `Bool`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Bool(false); + /// let converted_value = Conversion.candyToPBool(value); + /// ``` + /// Note: Throws if the underlying value is not a `#Bool`. + public func candyToBool(val : Candy) : Bool { + + switch(val){ + case(#Bool(val)){val}; + case(_){assert(false);/*unreachable*/false;}; + }; + }; + + /// Convert a `Candy` to `Blob`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Principal(Principal.fromText("abc")); + /// let converted_value = Conversion.candyToBlob(value); + /// ``` + public func candyToBlob(val : Candy) : Blob { + + switch(val){ + case(#Blob(val)){val}; + case(#Bytes(val)){Blob.fromArray(StableBuffer.toArray(val))}; + case(#Text(val)){ + Blob.fromArray(textToBytes(val)) + }; + case(#Int(val)){ + Blob.fromArray(intToBytes(val)) + }; + case(#Nat(val)){ + Blob.fromArray(natToBytes(val)) + }; + case(#Nat8(val)){ + + Blob.fromArray([val]) + }; + case(#Nat16(val)){ + Blob.fromArray(nat16ToBytes(val)) + }; + case(#Nat32(val)){ + Blob.fromArray(nat32ToBytes(val)) + }; + case(#Nat64(val)){ + Blob.fromArray(nat64ToBytes(val)) + }; + case(#Principal(val)){ + Principal.toBlob(val); + }; + //todo: could add all conversions here + case(_){assert(false);/*unreachable*/"\00";}; + }; + }; + + /// Convert a `Candy` to `[Candy]` + /// + /// The conversion is done by getting the array of candy values of the #Array. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Array([1, 2, 3]); + /// let converted_value = Conversion.candyToValueArray(value); + /// ``` + /// Note: Throws if the underlying value is not an `#Array`. + public func candyToValueArray(val : Candy) : [Candy] { + switch(val){ + case(#Array(val)){StableBuffer.toArray(val)}; + //todo: could add all conversions here + case(_){assert(false);/*unreachable*/[];}; + }; + }; + + /// Convert a `Candy` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Principal(Principal.fromText("abc")); + /// let value_as_bytes = Conversion.candyToBytes(value); + /// ``` + public func candyToBytes(val : Candy) : [Nat8]{ + switch(val){ + case(#Int(val)){intToBytes(val)}; + case(#Int8(val)){candyToBytes(#Int(candyToInt(#Int8(val))))}; + case(#Int16(val)){candyToBytes(#Int(candyToInt(#Int16(val))))}; + case(#Int32(val)){candyToBytes(#Int(candyToInt(#Int32(val))))}; + case(#Int64(val)){candyToBytes(#Int(candyToInt(#Int64(val))))}; + case(#Nat(val)){natToBytes(val)}; + case(#Nat8(val)){ [val]}; + case(#Nat16(val)){nat16ToBytes(val)}; + case(#Nat32(val)){nat32ToBytes(val)}; + case(#Nat64(val)){nat64ToBytes(val)}; + case(#Float(val)){Prelude.nyi()}; + case(#Text(val)){textToBytes(val)}; + case(#Bool(val)){boolToBytes(val)}; + case(#Blob(val)){ Blob.toArray(val)}; + case(#Class(val)){Prelude.nyi()}; + case(#Principal(val)){principalToBytes(val)}; + case(#Option(val)){Prelude.nyi()}; + case(#Array(val)){Prelude.nyi()}; + case(#Bytes(val)){StableBuffer.toArray(val)}; + case(#Floats(val)){Prelude.nyi()}; + case(#Nats(val)){Prelude.nyi()}; + case(#Ints(val)){Prelude.nyi()}; + case(#ValueMap(val)){Prelude.nyi()}; + case(#Map(val)){Prelude.nyi()}; + case(#Set(val)){Prelude.nyi()}; + } + }; + + /// Convert a `Candy` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Principal(Principal.fromText("abc")); + /// let value_as_buffer = Conversion.candyToBytesBuffer(value); + /// ``` + /// + /// Note: Throws if the underlying value isn't convertible. + public func candyToBytesBuffer(val : Candy) : Buffer.Buffer{ + switch (val){ + case(#Bytes(val)){Buffer.fromArray(StableBuffer.toArray(val))}; + case(_){ + toBuffer(candyToBytes(val));//may throw for uncovertable types + }; + }; + }; + + /// Convert a `Candy` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Nat(102); + /// let value_as_floats_buffer = Conversion.candyToFloatsBuffer(value); + /// ``` + /// Note: Throws if the underlying value isn't convertible. + public func candyToFloatsBuffer(val : Candy) : Buffer.Buffer{ + switch (val){ + case(#Floats(val)){ + stableBufferToBuffer(val); + }; + case(_){ + toBuffer([candyToFloat(val)]); //may throw for unconvertable types + }; + }; + }; + + /// Convert a `Candy` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Nat(102); + /// let value_as_nats_buffer = Conversion.candyToNatsBuffer(value); + /// ``` + /// Note: Throws if the underlying value isn't convertible. + public func candyToNatsBuffer(val : Candy) : Buffer.Buffer{ + switch (val){ + case(#Nats(val)){ + stableBufferToBuffer(val); + }; + case(_){ + toBuffer([candyToNat(val)]); //may throw for unconvertable types + }; + }; + }; + + /// Convert a `Candy` to `Map` + /// + /// Example: + /// ```motoko include=import + /// let map = Map.new(); + /// Map.put(map, thash, "akey", #Text("value")); + /// let value: Candy = #Map(map); + /// let value_as_nats_buffer = Conversion.candyToMap(value); + /// ``` + /// Note: Throws if the underlying value isn't convertible. + public func candyToMap(val : Candy) : Map.Map{ + switch (val){ + case(#Map(val)){ + return val; + }; + case(_){ + Prelude.nyi(); //will throw for unconvertable types + }; + }; + }; + + /// Example: + /// ```motoko include=import + /// let map = Map.new(); + /// Map.put(map, candyHashTool, #Text("akey"), #Text("value")); + /// let value: Candy = #ValueMapMap(map); + /// let value_as_nats_buffer = Conversion.candyToValueMap(value); + /// ``` + /// Note: Throws if the underlying value isn't convertible. + public func candyToValueMap(val : Candy) : Map.Map{ + switch (val){ + case(#ValueMap(val)){ + return val; + }; + case(_){ + Prelude.nyi(); //will throw for unconvertable types + }; + }; + }; + + /// Example: + /// ```motoko include=import + /// let map = Set.new(); + /// Set.put(map, candyHashTool, #Text("akey")); + /// let value: Candy = #Set(map); + /// let value_as_nats_buffer = Conversion.candyToSet(value); + /// ``` + /// Note: Throws if the underlying value isn't convertible. + public func candyToSet(val : Candy) : Set.Set{ + switch (val){ + case(#Set(val)){ + return val; + }; + case(_){ + Prelude.nyi(); //will throw for unconvertable types + }; + }; + }; + + /// Convert a `Candy` to `Map` + /// + /// Example: + /// ```motoko include=import + /// let map = Map.new(); + /// Map.put(map, thash, "akey", {name="test";value=#Text("value"); immutable=true;); + /// let value: Candy = #Class(map); + /// let value_as_nats_buffer = Conversion.candyToPropertyMap(value); + /// ``` + /// Note: Throws if the underlying value isn't convertible. + public func candyToPropertyMap(val : Candy) : Map.Map{ + switch (val){ + case(#Class(val)){ + return val; + }; + case(_){ + Prelude.nyi(); //will throw for unconvertable types + }; + }; + }; + + /// Convert a `CandyShared` to `Nat`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int16(15); + /// let converted_value = Conversion.candySharedToNat(value); + /// ``` + /// Note: Throws if the underlying value overflows or is negative. + public func candySharedToNat(val : CandyShared) : Nat { + + switch(val){ + case(#Nat(val)){ val}; + case(#Nat8(val)){ Nat8.toNat(val)}; + case(#Nat16(val)){ Nat16.toNat(val)}; + case(#Nat32(val)){Nat32.toNat(val)}; + case(#Nat64(val)){ Nat64.toNat(val)}; + case(#Float(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){assert false;};//will throw on negative + + Int.abs(val)}; + case(#Int8(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat(#Int(Int8.toInt(Int8.abs(val))))};//will throw on overflow + case(#Int16(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat(#Int(Int16.toInt(Int16.abs(val))))};//will throw on overflow + case(#Int32(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat(#Int(Int32.toInt(Int32.abs(val))))};//will throw on overflow + case(#Int64(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat(#Int(Int64.toInt(Int64.abs(val))))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `CandyShared` to `Nat8`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int8(15); + /// let converted_value = Conversion.candySharedToNat8(value); + /// ``` + /// Note: Throws if the underlying value overflows or is negative. + public func candySharedToNat8(val : CandyShared) : Nat8 { + + switch(val){ + case(#Nat8(val)){ val}; + case(#Nat(val)){ Nat8.fromNat(val)};//will throw on overflow + case(#Nat16(val)){ Nat8.fromNat(Nat16.toNat(val))};//will throw on overflow + case(#Nat32(val)){ Nat8.fromNat(Nat32.toNat(val))};//will throw on overflow + case(#Nat64(val)){ Nat8.fromNat(Nat64.toNat(val))};//will throw on overflow + case(#Float(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat8(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat8(#Nat(Int.abs(val)))}; + case(#Int8(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat8(#Int(Int8.toInt(Int8.abs(val))))};//will throw on overflow + case(#Int16(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat8(#Int(Int16.toInt(Int16.abs(val))))};//will throw on overflow + case(#Int32(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat8(#Int(Int32.toInt(Int32.abs(val))))};//will throw on overflow + case(#Int64(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat8(#Int(Int64.toInt(Int64.abs(val))))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `CandyShared` to `Nat16`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int16(15); + /// let converted_value = Conversion.candySharedToNat16(value); + /// ``` + /// Note: Throws if the underlying value overflows or is negative. + public func candySharedToNat16(val : CandyShared) : Nat16 { + + switch(val){ + case(#Nat16(val)){ val}; + case(#Nat8(val)){ Nat16.fromNat(Nat8.toNat(val))}; + case(#Nat(val)){ Nat16.fromNat(val)};//will throw on overflow + case(#Nat32(val)){ Nat16.fromNat(Nat32.toNat(val))};//will throw on overflow + case(#Nat64(val)){ Nat16.fromNat(Nat64.toNat(val))};//will throw on overflow + case(#Float(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat16(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat16(#Nat(Int.abs(val)))}; + case(#Int8(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat16(#Int(Int8.toInt(Int8.abs(val))))};//will throw on overflow + case(#Int16(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat16(#Int(Int16.toInt(Int16.abs(val))))};//will throw on overflow + case(#Int32(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat16(#Int(Int32.toInt(Int32.abs(val))))};//will throw on overflow + case(#Int64(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat16(#Int(Int64.toInt(Int64.abs(val))))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `CandyShared` to `Nat32`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int32(15); + /// let converted_value = Conversion.candySharedToNat(value); + /// ``` + /// Note: Throws if the underlying value overflows or is negative. + public func candySharedToNat32(val : CandyShared) : Nat32 { + + switch(val){ + case(#Nat32(val)){val}; + case(#Nat16(val)){Nat32.fromNat(Nat16.toNat(val))}; + case(#Nat8(val)){ Nat32.fromNat(Nat8.toNat(val))}; + case(#Nat(val)){ Nat32.fromNat(val)};//will throw on overflow + case(#Float(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat32(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat32(#Nat(Int.abs(val)))}; + case(#Int8(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat32(#Int(Int8.toInt(Int8.abs(val))))};//will throw on overflow + case(#Int16(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat32(#Int(Int16.toInt(Int16.abs(val))))};//will throw on overflow + case(#Int32(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat32(#Int(Int32.toInt(Int32.abs(val))))};//will throw on overflow + case(#Int64(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat32(#Int(Int64.toInt(Int64.abs(val))))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `CandyShared` to `Nat64`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int16(15); + /// let converted_value = Conversion.candySharedToNat64(value); + /// ``` + /// Note: Throws if the underlying value is negative. + public func candySharedToNat64(val : CandyShared) : Nat64 { + + switch(val){ + case(#Nat64(val)){ val}; + case(#Nat32(val)){ Nat64.fromNat(Nat32.toNat(val))}; + case(#Nat16(val)){ Nat64.fromNat(Nat16.toNat(val))}; + case(#Nat8(val)){ Nat64.fromNat(Nat8.toNat(val))}; + case(#Nat(val)){ Nat64.fromNat(val)}; + case(#Float(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat64(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat64(#Nat(Int.abs(val)))}; + case(#Int8(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat64(#Int(Int8.toInt(Int8.abs(val))))};//will throw on overflow + case(#Int16(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat64(#Int(Int16.toInt(Int16.abs(val))))};//will throw on overflow + case(#Int32(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat64(#Int(Int32.toInt(Int32.abs(val))))};//will throw on overflow + case(#Int64(val)){ + if(val < 0){assert false;};//will throw on negative + candySharedToNat64(#Int(Int64.toInt(Int64.abs(val))))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `CandyShared` to `Int`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int16(15); + /// let converted_value = Conversion.candySharedToInt(value); + /// ``` + /// Note: Throws if the underlying value overflows. + public func candySharedToInt(val : CandyShared) : Int { + switch(val){ + case(#Int(val)){val}; + case(#Int8(val)){ Int8.toInt(val)}; + case(#Int16(val)){ Int16.toInt(val)}; + case(#Int32(val)){ Int32.toInt(val)}; + case(#Int64(val)){ Int64.toInt(val)}; + case(#Nat(val)){ val}; + case(#Nat8(val)){Nat8.toNat(val)}; + case(#Nat16(val)){Nat16.toNat(val)}; + case(#Nat32(val)){Nat32.toNat(val)}; + case(#Nat64(val)){Nat64.toNat(val)}; + case(#Float(val)){Float.toInt(Float.nearest(val))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `CandyShared` to `Int8`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Nat8(11); + /// let converted_value = Conversion.candySharedToInt8(value); + /// ``` + /// Note: Throws if the underlying value overflows. + public func candySharedToInt8(val : CandyShared) : Int8 { + switch(val){ + case(#Int8(val)){ val}; + case(#Int(val)){ Int8.fromInt(val)};//will throw on overflow + case(#Int16(val)){ Int8.fromInt(Int16.toInt(val))};//will throw on overflow + case(#Int32(val)){ Int8.fromInt(Int32.toInt(val))};//will throw on overflow + case(#Int64(val)){ Int8.fromInt(Int64.toInt(val))};//will throw on overflow + case(#Nat8(val)){ Int8.fromNat8(val)}; + case(#Nat(val)){Int8.fromNat8(candySharedToNat8(#Nat(val)))};//will throw on overflow + case(#Nat16(val)){Int8.fromNat8(candySharedToNat8(#Nat16(val)))};//will throw on overflow + case(#Nat32(val)){Int8.fromNat8(candySharedToNat8(#Nat32(val)))};//will throw on overflow + case(#Nat64(val)){Int8.fromNat8(candySharedToNat8(#Nat64(val)))};//will throw on overflow + case(#Float(val)){ Int8.fromInt(Float.toInt(Float.nearest(val)))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `CandyShared` to `Int16`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Float(10); + /// let converted_value = Conversion.candySharedToInt16(value); + /// ``` + /// Note: Throws if the underlying value overflows. + public func candySharedToInt16(val : CandyShared) : Int16 { + switch(val){ + case(#Int16(val)){ val}; + case(#Int8(val)){ Int16.fromInt(Int8.toInt(val))}; + case(#Int(val)){ Int16.fromInt(val)};//will throw on overflow + case(#Int32(val)){ Int16.fromInt(Int32.toInt(val))};//will throw on overflow + case(#Int64(val)){ Int16.fromInt(Int64.toInt(val))};//will throw on overflow + case(#Nat8(val)){Int16.fromNat16(candySharedToNat16(#Nat8(val)))}; + case(#Nat(val)){Int16.fromNat16(candySharedToNat16(#Nat(val)))};//will throw on overflow + case(#Nat16(val)){ Int16.fromNat16(val)}; + case(#Nat32(val)){Int16.fromNat16(candySharedToNat16(#Nat32(val)))};//will throw on overflow + case(#Nat64(val)){Int16.fromNat16(candySharedToNat16(#Nat64(val)))};//will throw on overflow + case(#Float(val)){ Int16.fromInt(Float.toInt(Float.nearest(val)))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `CandyShared` to `Int32`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Nat32(1111); + /// let converted_value = Conversion.candySharedToInt32(value); + /// ``` + /// Note: Throws if the underlying value overflows. + public func candySharedToInt32(val : CandyShared) : Int32 { + switch(val){ + case(#Int32(val)){ val}; + case(#Int16(val)){ Int32.fromInt(Int16.toInt(val))}; + case(#Int8(val)){ Int32.fromInt(Int8.toInt(val))}; + case(#Int(val)){ Int32.fromInt(val)};//will throw on overflow + case(#Nat8(val)){Int32.fromNat32(candySharedToNat32(#Nat8(val)))}; + case(#Nat(val)){Int32.fromNat32(candySharedToNat32(#Nat(val)))};//will throw on overflow + case(#Nat16(val)){Int32.fromNat32(candySharedToNat32(#Nat16(val)))}; + case(#Nat32(val)){ Int32.fromNat32(val)}; + case(#Nat64(val)){Int32.fromNat32(candySharedToNat32(#Nat64(val)))};//will throw on overflow + case(#Float(val)){ Int32.fromInt(Float.toInt(Float.nearest(val)))};//will throw on overflow + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `CandyShared` to `Int64`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Nat64(12345); + /// let converted_value = Conversion.candySharedToInt64(value); + /// ``` + /// Note: Throws if the underlying value overflows. + public func candySharedToInt64(val : CandyShared) : Int64 { + switch(val){ + case(#Int64(val)){ val}; + case(#Int32(val)){ Int64.fromInt(Int32.toInt(val))}; + case(#Int16(val)){ Int64.fromInt(Int16.toInt(val))}; + case(#Int8(val)){ Int64.fromInt(Int8.toInt(val))}; + case(#Int(val)){ Int64.fromInt(val)};//will throw on overflow + case(#Nat8(val)){Int64.fromNat64(candySharedToNat64(#Nat8(val)))}; + case(#Nat(val)){Int64.fromNat64(candySharedToNat64(#Nat(val)))};//will throw on overflow + case(#Nat16(val)){Int64.fromNat64(candySharedToNat64(#Nat16(val)))}; + case(#Nat32(val)){Int64.fromNat64(candySharedToNat64(#Nat32(val)))};//will throw on overflow + case(#Nat64(val)){ Int64.fromNat64(val)}; + case(#Float(val)){ Float.toInt64(Float.nearest(val))}; + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `CandyShared` to `Float`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int16(11); + /// let converted_value = Conversion.candySharedToFloat(value); + /// ``` + /// Note: Throws if the underlying value overflows. + public func candySharedToFloat(val : CandyShared) : Float { + switch(val){ + case(#Float(val)){ val}; + case(#Int64(val)){ Float.fromInt64(val)}; + case(#Int32(val)){candySharedToFloat(#Int(Int32.toInt(val)))}; + case(#Int16(val)){candySharedToFloat(#Int(Int16.toInt(val)))}; + case(#Int8(val)){candySharedToFloat(#Int(Int8.toInt(val)))}; + case(#Int(val)){ Float.fromInt(val)}; + case(#Nat8(val)){candySharedToFloat(#Int(Nat8.toNat(val)))}; + case(#Nat(val)){candySharedToFloat(#Int(val))};//will throw on overflow + case(#Nat16(val)){candySharedToFloat(#Int(Nat16.toNat(val)))}; + case(#Nat32(val)){candySharedToFloat(#Int(Nat32.toNat(val)))};//will throw on overflow + case(#Nat64(val)){candySharedToFloat(#Int(Nat64.toNat(val)))}; + case(_){assert(false);/*unreachable*/0;}; + }; + }; + + /// Convert a `CandyShared` to `Text`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Float(11); + /// let converted_value = Conversion.candySharedToText(value); + /// ``` + public func candySharedToText(val : CandyShared) : Text { + switch(val){ + case(#Text(val)){ val}; + case(#Nat64(val)){ Nat64.toText(val)}; + case(#Nat32(val)){ Nat32.toText(val)}; + case(#Nat16(val)){ Nat16.toText(val)}; + case(#Nat8(val)){ Nat8.toText(val)}; + case(#Nat(val)){ Nat.toText(val)}; + case(#Int64(val)){ Int64.toText(val)}; + case(#Int32(val)){ Int32.toText(val)}; + case(#Int16(val)){ Int16.toText(val)}; + case(#Int8(val)){ Int8.toText(val)}; + case(#Int(val)){ Int.toText(val)}; + case(#Bool(val)){ Bool.toText(val)}; + case(#Float(val)){ Float.format(#exact, val)}; + case(#Option(val)){ + switch(val){ + case(null){ "null"}; + case(?val){candySharedToText(val)}; + }; + }; + //blob + case(#Blob(val)){ + return Hex.encode(Blob.toArray(val)); + }; + //class + case(#Class(val)){ //this is currently not parseable and should probably just be used for debuging. It would be nice to output candid. + + var t = "{"; + for(thisItem in val.vals()){ + t := t # thisItem.name # ": " # (if(thisItem.immutable == false){"var "}else{""}) # candySharedToText(thisItem.value) # "; "; + }; + + return Text.trimEnd(t, #text(" ")) # "}"; + + + }; + //principal + case(#Principal(val)){ Principal.toText(val)}; + //array + case(#Array(val)){ + + var t = "["; + for(thisItem in val.vals()){ + t := t # "{" # candySharedToText(thisItem) # "} "; + }; + + return Text.trimEnd(t, #text(" ")) # "]"; + + }; + //floats + case(#Floats(val)){ + + var t = "["; + for(thisItem in val.vals()){ + t := t # Float.format(#exact, thisItem) # " "; + }; + + return Text.trimEnd(t, #text(" ")) # "]"; + + }; + //Nats + case(#Nats(val)){ + + var t = "["; + for(thisItem in val.vals()){ + t := t # Nat.toText(thisItem) # " "; + }; + + return Text.trimEnd(t, #text(" ")) # "]"; + + }; + //Ints + case(#Ints(val)){ + + var t = "["; + for(thisItem in val.vals()){ + t := t # Int.toText(thisItem) # " "; + }; + + return Text.trimEnd(t, #text(" ")) # "]"; + + }; + //bytes + case(#Bytes(val)){ + + return Hex.encode(val); + + }; + case(#Set(val)){ //this is currently not parseable and should probably just be used for debuging. It would be nice to output candid. + + var t = "["; + for(thisItem in val.vals()){ + t := t # "{" # candySharedToText(thisItem) # "} "; + }; + + return Text.trimEnd(t, #text(" ")) # "]"; + + + }; + case(#Map(val)){ //this is currently not parseable and should probably just be used for debuging. It would be nice to output candid. + + var t = "{"; + for(thisItem in val.vals()){ + t := t # thisItem.0 # ": " # candySharedToText(thisItem.1) # "; "; + }; + + return Text.trimEnd(t, #text(" ")) # "}"; + + + }; + case(#ValueMap(val)){ //this is currently not parseable and should probably just be used for debuging. It would be nice to output candid. + + var t = "{"; + for(thisItem in val.vals()){ + t := t # candySharedToText(thisItem.0) # ": " # candySharedToText(thisItem.1) # "; "; + }; + + return Text.trimEnd(t, #text(" ")) # "}"; + + + }; + //case(_){assert(false);/*unreachable*/"";}; + }; + }; + + /// Convert a `CandyShared` to `Principal`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Principal(Principal.fromText("abc")); + /// let converted_value = Conversion.candySharedToPrincipal(value); + /// ``` + /// Note: Throws if the underlying value is not a `#Principal`. + public func candySharedToPrincipal(val : CandyShared) : Principal { + switch(val){ + case(#Principal(val)){ val}; + case(_){assert(false);/*unreachable*/Principal.fromText("");}; + }; + }; + + /// Convert a `CandyShared` to `Principal`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Bool(true); + /// let converted_value = Conversion.candySharedToPrincipal(value); + /// ``` + /// Note: Throws if the underlying value is not a `#Bool`. + public func candySharedToBool(val : CandyShared) : Bool { + switch(val){ + case(#Bool(val)){ val}; + case(_){assert(false);/*unreachable*/false;}; + }; + }; + + /// Convert a `CandyShared` to `Blob`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Principal(Principal.fromText("abc")); + /// let converted_value = Conversion.candySharedToBlob(value); + /// ``` + public func candySharedToBlob(val : CandyShared) : Blob { + switch(val){ + case(#Blob(val)){ val}; + case(#Bytes(val)){ + Blob.fromArray(val); + }; + case(#Text(val)){ + Blob.fromArray(textToBytes(val)) + }; + case(#Int(val)){ + Blob.fromArray(intToBytes(val)) + }; + case(#Nat(val)){ + Blob.fromArray(natToBytes(val)) + }; + case(#Nat8(val)){ + + Blob.fromArray([val]) + }; + case(#Nat16(val)){ + Blob.fromArray(nat16ToBytes(val)) + }; + case(#Nat32(val)){ + Blob.fromArray(nat32ToBytes(val)) + }; + case(#Nat64(val)){ + Blob.fromArray(nat64ToBytes(val)) + }; + case(#Principal(val)){ + + Principal.toBlob(val); + }; + //todo: could add all conversions here + case(_){assert(false);/*unreachable*/"\00";}; + }; + }; + + /// Convert a `CandyShared` to `[CandyShared]` + /// + /// The conversion is done by getting the array of candy values of the #Array. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Array([1, 2, 3]); + /// let converted_value = Conversion.candySharedToValueArray(value); + /// ``` + /// Note: Throws if the underlying value is not an `#Array`. + public func candySharedToValueArray(val : CandyShared) : [CandyShared] { + switch(val){ + case(#Array(val)){val}; + //todo: could add all conversions here + case(_){assert(false);/*unreachable*/[];}; + }; + }; + + /// Convert a `CandyShared` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Principal(Principal.fromText("abc")); + /// let value_as_bytes = Conversion.candySharedToBytes(value); + /// ``` + public func candySharedToBytes(val : CandyShared) : [Nat8]{ + switch(val){ + case(#Int(val)){intToBytes(val)}; + case(#Int8(val)){candySharedToBytes(#Int(candySharedToInt(#Int8(val))))}; + case(#Int16(val)){candySharedToBytes(#Int(candySharedToInt(#Int16(val))))}; + case(#Int32(val)){candySharedToBytes(#Int(candySharedToInt(#Int32(val))))}; + case(#Int64(val)){candySharedToBytes(#Int(candySharedToInt(#Int64(val))))}; + case(#Nat(val)){ natToBytes(val)}; + case(#Nat8(val)){ [val]}; + case(#Nat16(val)){nat16ToBytes(val)}; + case(#Nat32(val)){nat32ToBytes(val)}; + case(#Nat64(val)){nat64ToBytes(val)}; + case(#Float(val)){Prelude.nyi()}; + case(#Text(val)){textToBytes(val)}; + case(#Bool(val)){boolToBytes(val)}; + case(#Blob(val)){ Blob.toArray(val)}; + case(#Class(val)){Prelude.nyi()}; + case(#Principal(val)){principalToBytes(val)}; + case(#Option(val)){Prelude.nyi()}; + case(#Array(val)){Prelude.nyi()}; + case(#Bytes(val)){val}; + case(#Floats(val)){Prelude.nyi()}; + case(#Nats(val)){Prelude.nyi()}; + case(#Ints(val)){Prelude.nyi()}; + case(#ValueMap(val)){Prelude.nyi()}; + case(#Map(val)){Prelude.nyi()}; + case(#Set(val)){Prelude.nyi()}; + } + }; + + /// Convert a `CandyShared` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Principal(Principal.fromText("abc")); + /// let value_as_buffer = Conversion.candySharedToBytes(value); + /// ``` + /// + /// Note: Throws if the underlying value isn't convertible. + public func candySharedToBytesBuffer(val : CandyShared) : Buffer.Buffer{ + switch (val){ + case(#Bytes(val)){toBuffer(val)}; + case(_){ + toBuffer(candySharedToBytes(val));//may throw for uncovertable types + }; + }; + }; + + /// Convert a `CandyShared` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Nat(102); + /// let value_as_floats_buffer = Conversion.candySharedToFloatsBuffer(value); + /// ``` + /// Note: Throws if the underlying value isn't convertible. + public func candySharedToFloatsBuffer(val : CandyShared) : Buffer.Buffer{ + switch (val){ + case(#Floats(val)){ + toBuffer(val); + }; + case(_){ + toBuffer([candySharedToFloat(val)]); //may throw for unconvertable types + }; + }; + }; + + /// Convert a `CandyShared` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Nat(102); + /// let value_as_nats_buffer = Conversion.candySharedToNatsBuffer(value); + /// ``` + /// Note: Throws if the underlying value isn't convertible. + public func candySharedToNatsBuffer(val : CandyShared) : Buffer.Buffer{ + switch (val){ + case(#Nats(val)){ + toBuffer(val); + }; + case(_){ + toBuffer([candySharedToNat(val)]); //may throw for unconvertable types + }; + }; + }; + + /// Convert a `CandyShared` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int(102); + /// let value_as_nats_buffer = Conversion.candySharedToIntsBuffer(value); + /// ``` + /// Note: Throws if the underlying value isn't convertible. + public func candySharedToIntsBuffer(val : CandyShared) : Buffer.Buffer{ + switch (val){ + case(#Ints(val)){ + toBuffer(val); + }; + case(_){ + toBuffer([candySharedToInt(val)]); //may throw for unconvertable types + }; + }; + }; + + ////////////////////////////////////////////////////////////////////// + // The following functions easily creates a buffer from an arry of any type + ////////////////////////////////////////////////////////////////////// + + /// Create a `Buffer` from [T] where T can be of any type. + /// + /// Example: + /// ```motoko include=import + /// let array = [1, 2, 3]; + /// let buf = Conversion.toBuffer(array); + /// ``` + public func toBuffer(x :[T]) : Buffer.Buffer{ + let thisBuffer = Buffer.Buffer(x.size()); + for(thisItem in x.vals()){ + thisBuffer.add(thisItem); + }; + return thisBuffer; + }; + + /// Create a `Buffer` from `StableBuffer` where T can be of any type. + /// + /// Example: + /// ```motoko include=import + /// let stable_buff = StableBuffer.fromArray([1, 2, 3]); + /// let buff = Conversion.stableBufferToBuffer(stable_buff); + /// ``` + public func stableBufferToBuffer(x : StableBuffer) : Buffer.Buffer{ + let thisBuffer = Buffer.Buffer(StableBuffer.size(x)); + for(thisItem in StableBuffer.vals(x)){ + thisBuffer.add(thisItem); + }; + return thisBuffer; + }; + + ////////////////////////////////////////////////////////////////////// + // The following functions convert standard types to Byte arrays + // From there you can easily get to blobs if necessary with the Blob package + ////////////////////////////////////////////////////////////////////// + + /// Convert a `Nat` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let value: Nat = 150; + /// let bytes = Conversion.natToBytes(value); + /// ``` + public func natToBytes(n : Nat) : [Nat8] { + var a : Nat8 = 0; + var b : Nat = n; + var bytes = List.nil(); + var test = true; + while test { + a := Nat8.fromNat(b % 256); + b := b / 256; + bytes := List.push(a, bytes); + test := b > 0; + }; + List.toArray(bytes); + }; + + /// Convert a `Nat64` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let value: Nat64 = 150; + /// let bytes = Conversion.nat64ToBytes(value); + /// ``` + public func nat64ToBytes(x : Nat64) : [Nat8] { + [ Nat8.fromNat(Nat64.toNat((x >> 56) & (255))), + Nat8.fromNat(Nat64.toNat((x >> 48) & (255))), + Nat8.fromNat(Nat64.toNat((x >> 40) & (255))), + Nat8.fromNat(Nat64.toNat((x >> 32) & (255))), + Nat8.fromNat(Nat64.toNat((x >> 24) & (255))), + Nat8.fromNat(Nat64.toNat((x >> 16) & (255))), + Nat8.fromNat(Nat64.toNat((x >> 8) & (255))), + Nat8.fromNat(Nat64.toNat((x & 255))) ]; + }; + + /// Convert a `Nat32` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let value: Nat32 = 150; + /// let bytes = Conversion.nat32ToBytes(value); + /// ``` + public func nat32ToBytes(x : Nat32) : [Nat8] { + [ Nat8.fromNat(Nat32.toNat((x >> 24) & (255))), + Nat8.fromNat(Nat32.toNat((x >> 16) & (255))), + Nat8.fromNat(Nat32.toNat((x >> 8) & (255))), + Nat8.fromNat(Nat32.toNat((x & 255))) ]; + }; + + /// Convert a `Nat16` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let value: Nat16 = 150; + /// let bytes = Conversion.nat16ToBytes(value); + /// ``` + public func nat16ToBytes(x : Nat16) : [Nat8] { + [ Nat8.fromNat(Nat16.toNat((x >> 8) & (255))), + Nat8.fromNat(Nat16.toNat((x & 255))) ]; + }; + + /// Convert Bytes(`[Nat8]`) to `Nat16` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [1, 2, 3, 4]; + /// let value = Conversion.bytesToNat16(bytes); + /// ``` + public func bytesToNat16(bytes: [Nat8]) : Nat16{ + (Nat16.fromNat(Nat8.toNat(bytes[0])) << 8) + + (Nat16.fromNat(Nat8.toNat(bytes[1]))); + }; + + /// Convert Bytes(`[Nat8]`) to `Nat32` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [1, 2, 3, 4]; + /// let value = Conversion.bytesToNat32(bytes); + /// ``` + public func bytesToNat32(bytes: [Nat8]) : Nat32{ + (Nat32.fromNat(Nat8.toNat(bytes[0])) << 24) + + (Nat32.fromNat(Nat8.toNat(bytes[1])) << 16) + + (Nat32.fromNat(Nat8.toNat(bytes[2])) << 8) + + (Nat32.fromNat(Nat8.toNat(bytes[3]))); + }; + + /// Convert Bytes(`[Nat8]`) to `Nat64` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [1, 2, 3, 4]; + /// let value = Conversion.bytesToNat64(bytes); + /// ``` + public func bytesToNat64(bytes: [Nat8]) : Nat64{ + + (Nat64.fromNat(Nat8.toNat(bytes[0])) << 56) + + (Nat64.fromNat(Nat8.toNat(bytes[1])) << 48) + + (Nat64.fromNat(Nat8.toNat(bytes[2])) << 40) + + (Nat64.fromNat(Nat8.toNat(bytes[3])) << 32) + + (Nat64.fromNat(Nat8.toNat(bytes[4])) << 24) + + (Nat64.fromNat(Nat8.toNat(bytes[5])) << 16) + + (Nat64.fromNat(Nat8.toNat(bytes[6])) << 8) + + (Nat64.fromNat(Nat8.toNat(bytes[7]))); + }; + + /// Convert Bytes(`[Nat8]`) to `Nat` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [1, 2, 3, 4]; + /// let value = Conversion.bytesToNat(bytes); + /// ``` + public func bytesToNat(bytes : [Nat8]) : Nat { + var n : Nat = 0; + var i = 0; + Array.foldRight(bytes, (), func (byte, _) { + n += Nat8.toNat(byte) * 256 ** i; + i += 1; + return; + }); + return n; + }; + + /// Convert `Text` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let t = "sample_text"; + /// let buf = Conversion.textToByteBuffer(t); + /// ``` + public func textToByteBuffer(_text : Text) : Buffer.Buffer{ + let result : Buffer.Buffer = Buffer.Buffer((_text.size() * 4) +4); + for(thisChar in _text.chars()){ + for(thisByte in nat32ToBytes(Char.toNat32(thisChar)).vals()){ + result.add(thisByte); + }; + }; + return result; + }; + + /// Convert `Text` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let t = "sample_text"; + /// let bytes = Conversion.textToBytes(t); + /// ``` + public func textToBytes(_text : Text) : [Nat8]{ + return Buffer.toArray(textToByteBuffer(_text)); + }; + + /// Encode `Text` to a giant int(`?Nat`) + /// + /// Example: + /// ```motoko include=import + /// let t = "sample_text"; + /// let encoded_t = Conversion.encodeTextAsNat(t); + /// ``` + public func encodeTextAsNat(phrase : Text) : ?Nat { + var theSum : Nat = 0; + Iter.iterate(Text.toIter(phrase), func (x : Char, n : Nat){ + //todo: check for digits + theSum := theSum + ((Nat32.toNat(Char.toNat32(x)) - 48) * 10 ** (phrase.size()-n-1)); + }); + return ?theSum; + }; + + /// Convert `Text` to a `?Nat` + /// + /// Example: + /// ```motoko include=import + /// let t = "100"; + /// let t_as_nat = Conversion.textToNat(t); // 100 + /// ``` + /// + /// Note: Returns `null` if the text is empty. + public func textToNat( txt : Text) : ?Nat { + if(txt.size() > 0){ + let chars = txt.chars(); + var num : Nat = 0; + for (v in chars){ + let charToNum = Nat32.toNat(Char.toNat32(v)-48); + if(charToNum >= 0 and charToNum <= 9){ + num := num * 10 + charToNum; + } else { + return null; + }; + }; + ?num; + }else { + return null; + }; + }; + + /// Convert `Property` to a `Text` + /// + /// Example: + /// ```motoko include=import + /// let prop: Property = { + /// name = "name"; + /// value = #Principal(Principal.fromText("abc")); + /// immutable = true; + /// }; + /// let prop_as_text = Conversion.propertyToText(t); + /// ``` + public func propertyToText(a: Types.Property):Text{candyToText(a.value)}; + + /// Convert `PropertyShared` to a `Text` + /// + /// Example: + /// ```motoko include=import + /// let prop: PropertyShared = { + /// name = "name"; + /// value = #Principal(Principal.fromText("abc")); + /// immutable = true; + /// }; + /// let prop_as_text = Conversion.propertyToText(t); + /// ``` + public func propertySharedToText(a: Types.PropertyShared):Text{candySharedToText(a.value)}; + + /// Convert `Candy` to `Properties` + /// + /// Example: + /// ```motoko include=import + /// let val: Candy = #Class([ + /// { + /// name = "prop1"; + /// value = #Principal(Principal.fromText("abc")); + /// immutable = true; + /// }, + /// { + /// name = "prop2"; + /// value = #Principal(Principal.fromText("abc")); + /// immutable = false; + /// } + /// ]); + /// let props = Conversion.candyToProperties(val); + /// ``` + /// Note: throws if the underlying value is not `#Class`. + public func candyToProperties(val : Candy) : Types.Properties { + switch(val){ + case(#Class(val)){ + Map.fromIter( + Map.entries(val) + , Map.thash)}; + case(_){assert(false);/*unreachable*/Map.new();}; + }; + }; + + /// Convert `Candy` to `Properties` + /// + /// Example: + /// ```motoko include=import + /// let val: Candy = #Class([ + /// { + /// name = "prop1"; + /// value = #Principal(Principal.fromText("abc")); + /// immutable = true; + /// }, + /// { + /// name = "prop2"; + /// value = #Principal(Principal.fromText("abc")); + /// immutable = false; + /// } + /// ]); + /// let props = Conversion.candyToProperties(val); + /// ``` + /// Note: throws if the underlying value is not `#Class`. + public func candySharedToProperties(val : CandyShared) : Types.PropertiesShared { + switch(val){ + case(#Class(val)){ + val; + }; + case(_){assert(false);/*unreachable*/[];}; + }; + }; + + /// Convert `[Nat8]` to a `Text` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [140, 145, 190, 192]; + /// let bytes_as_text = Conversion.bytesToText(bytes); + /// ``` + public func bytesToText(_bytes : [Nat8]) : Text{ + var result : Text = ""; + var aChar : [var Nat8] = [var 0, 0, 0, 0]; + + for(thisChar in Iter.range(0,_bytes.size())){ + if(thisChar > 0 and thisChar % 4 == 0){ + aChar[0] := _bytes[thisChar-4]; + aChar[1] := _bytes[thisChar-3]; + aChar[2] := _bytes[thisChar-2]; + aChar[3] := _bytes[thisChar-1]; + result := result # Char.toText(Char.fromNat32(bytesToNat32(Array.freeze(aChar)))); + }; + }; + return result; + }; + + /// Convert `Principal` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let p = Principal.fromText("xyz"); + /// let principal_as_bytes = Conversion.principalToBytes(p); + /// ``` + public func principalToBytes(_principal: Principal) : [Nat8]{ + return Blob.toArray(Principal.toBlob(_principal)); + }; + + /// Convert Bytes(`[Nat8]`) to `Principal` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [140, 145, 190, 192]; + /// let p = Conversion.bytesToPrincipal(bytes); + /// ``` + public func bytesToPrincipal(_bytes: [Nat8]) : Principal{ + return Principal.fromBlob(Blob.fromArray(_bytes)); + }; + + /// Convert `Principal` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let b = false; + /// let bool_as_bytes = Conversion.boolToBytes(b); + /// ``` + public func boolToBytes(_bool : Bool) : [Nat8]{ + if(_bool == true){ + return [1:Nat8]; + } else { + return [0:Nat8]; + }; + }; + + /// Convert Bytes(`[Nat8]`) to `Bool` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [1:Nat8]; + /// let b = Conversion.bytesToBool(bytes); // true + /// ``` + public func bytesToBool(_bytes : [Nat8]) : Bool{ + if(_bytes[0] == 0){ + return false; + } else { + return true; + }; + }; + + /// Convert `Int` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let i = 266; + /// let int_as_bytes = Conversion.intToBytes(b); // [0, 2, 10] + /// ``` + public func intToBytes(n : Int) : [Nat8]{ + var a : Nat8 = 0; + var c : Nat8 = if(n < 0){1}else{0}; + var b : Nat = Int.abs(n); + var bytes = List.nil(); + var test = true; + while test { + a := Nat8.fromNat(b % 128); + b := b / 128; + bytes := List.push(a, bytes); + test := b > 0; + }; + let result = toBuffer([c]); + result.append(toBuffer(List.toArray(bytes))); + Buffer.toArray(result); + //Array.append([c],List.toArray(bytes)); + }; + + /// Convert Bytes(`[Nat8]`) to `Int` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [0, 2, 10]; + /// let b = Conversion.bytesToBool(bytes); // 266 + /// ``` + public func bytesToInt(_bytes : [Nat8]) : Int{ + var n : Int = 0; + var i = 0; + let natBytes = Array.tabulate(_bytes.size() - 2, func(idx){_bytes[idx+1]}); + + Array.foldRight(natBytes, (), func (byte, _) { + n += Nat8.toNat(byte) * 128 ** i; + i += 1; + return; + }); + if(_bytes[0]==1){ + n *= -1; + }; + return n; + }; + + + /// Unwrap an Option value. + /// + /// If the underlying value is a #Option(T), T is returned, + /// Otherwise, the parameter is returned as it is. + /// + /// Example: + /// ```motoko include=import + /// let val: Candy = #Option(?#Principal(Principal.fromText("xyz"))); + /// let unwrapped_val = Conversion.unwrapOptionCandy(val); + /// ``` + public func unwrapOptionCandy(val : Candy): Candy{ + switch(val){ + case(#Option(val)){ + switch(val){ + case(null){ + return #Option(null); + }; + case(?val){ + return val; + } + }; + }; + case(_){val}; + }; + }; + + /// Unwrap an Option value. + /// + /// If the underlying value is a #Option(T), T is returned, + /// Otherwise, the parameter is returned as it is. + /// + /// Example: + /// ```motoko include=import + /// let val: CandyShared = #Option(?#Principal(Principal.fromText("xyz"))); + /// let unwrapped_val = Conversion.unwrapOptionCandy(val); + /// ``` + public func unwrapOptionCandyShared(val : CandyShared): CandyShared{ + switch(val){ + case(#Option(val)){ + switch(val){ + case(null){ + return #Option(null); + }; + case(?val){ + return val; + } + }; + }; + case(_){val}; + }; + }; + + ///converts a candyshared value to the reduced set of ValueShared used in many places like ICRC3. Some types not recoverable + public func CandySharedToValue(x: CandyShared) : ValueShared { + switch(x){ + case(#Text(x)) #Text(x); + case(#Map(x)) { + let buf = Buffer.Buffer<(Text, ValueShared)>(1); + for(thisItem in x.vals()){ + buf.add((thisItem.0, CandySharedToValue(thisItem.1))); + }; + #Map(Buffer.toArray(buf)); + }; + case(#Class(x)) { + let buf = Buffer.Buffer<(Text, ValueShared)>(1); + for(thisItem in x.vals()){ + buf.add((thisItem.name, CandySharedToValue(thisItem.value))); + }; + #Map(Buffer.toArray(buf)); + }; + case(#Int(x)) #Int(x); + case(#Int8(x)) #Int(Int8.toInt(x)); + case(#Int16(x)) #Int(Int16.toInt(x)); + case(#Int32(x)) #Int(Int32.toInt(x)); + case(#Int64(x)) #Int(Int64.toInt(x)); + case(#Ints(x)){ + #Array(Array.map(x, func(x: Int) : ValueShared { #Int(x)})); + }; + case(#Nat(x)) #Nat(x); + case(#Nat8(x)) #Nat(Nat8.toNat(x)); + case(#Nat16(x)) #Nat(Nat16.toNat(x)); + case(#Nat32(x)) #Nat(Nat32.toNat(x)); + case(#Nat64(x)) #Nat(Nat64.toNat(x)); + case(#Nats(x)){ + #Array(Array.map(x, func(x: Nat) : ValueShared { #Nat(x)})); + }; + case(#Bytes(x)){ + #Blob(Blob.fromArray(x)); + }; + case(#Array(x)) { + #Array(Array.map(x, CandySharedToValue)); + }; + case(#Blob(x)) #Blob(x); + case(#Bool(x)) #Blob(Blob.fromArray([if(x==true){1 : Nat8} else {0: Nat8}])); + case(#Float(x)){#Text(Float.format(#exact, x))}; + case(#Floats(x)){ + #Array(Array.map(x, func(x: Float) : ValueShared { CandySharedToValue(#Float(x))})); + }; + case(#Option(x)){ //empty array is null + switch(x){ + case(null) #Array([]); + case(?x) #Array([CandySharedToValue(x)]); + }; + }; + case(#Principal(x)){ + #Blob(Principal.toBlob(x)); + }; + case(#Set(x)) { + #Array(Array.map(x, func(x: CandyShared) : ValueShared { CandySharedToValue(x)})); + }; + case(#ValueMap(x)) { + #Array(Array.map<(CandyShared,CandyShared),ValueShared>(x, func(x: (CandyShared,CandyShared)) : ValueShared { #Array([CandySharedToValue(x.0), CandySharedToValue(x.1)])})); + }; + //case(_){assert(false);/*unreachable*/#Nat(0);}; + }; + + + }; + + ///converts a candy value to the reduced set of ValueShared used in many places like ICRC3. Some types not recoverable + public func CandyToValue(x: Candy) : ValueShared { + switch(x){ + case(#Text(x)) #Text(x); + case(#Map(x)) { + let buf = Buffer.Buffer<(Text, ValueShared)>(1); + for(thisItem in Map.entries(x)){ + buf.add((thisItem.0, CandyToValue(thisItem.1))); + }; + #Map(Buffer.toArray(buf)); + }; + case(#Class(x)) { + let buf = Buffer.Buffer<(Text, ValueShared)>(1); + for(thisItem in Map.entries(x)){ + buf.add((thisItem.1.name, CandyToValue(thisItem.1.value))); + }; + #Map(Buffer.toArray(buf)); + }; + case(#Int(x)) #Int(x); + case(#Int8(x)) #Int(Int8.toInt(x)); + case(#Int16(x)) #Int(Int16.toInt(x)); + case(#Int32(x)) #Int(Int32.toInt(x)); + case(#Int64(x)) #Int(Int64.toInt(x)); + case(#Ints(x)){ + #Array(StableBuffer.toArray(StableBuffer.map(x, func(x: Int) : ValueShared { #Int(x)}))); + }; + case(#Nat(x)) #Nat(x); + case(#Nat8(x)) #Nat(Nat8.toNat(x)); + case(#Nat16(x)) #Nat(Nat16.toNat(x)); + case(#Nat32(x)) #Nat(Nat32.toNat(x)); + case(#Nat64(x)) #Nat(Nat64.toNat(x)); + case(#Nats(x)){ + #Array(StableBuffer.toArray(StableBuffer.map(x, func(x: Nat) : ValueShared { #Nat(x)}))); + }; + case(#Bytes(x)){ + #Blob(Blob.fromArray(StableBuffer.toArray(x))); + }; + case(#Array(x)) { + #Array(StableBuffer.toArray(StableBuffer.map(x, CandyToValue))); + }; + case(#Blob(x)) #Blob(x); + case(#Bool(x)) #Blob(Blob.fromArray([if(x==true){1 : Nat8} else {0: Nat8}])); + case(#Float(x)){#Text(Float.format(#exact, x))}; + case(#Floats(x)){ + #Array(StableBuffer.toArray(StableBuffer.map(x, func(x: Float) : ValueShared { CandyToValue(#Float(x))}))); + }; + case(#Option(x)){ //empty array is null + switch(x){ + case(null) #Array([]); + case(?x) #Array([CandyToValue(x)]); + }; + }; + case(#Principal(x)){ + #Blob(Principal.toBlob(x)); + }; + case(#Set(x)) { + #Array(Iter.toArray(Iter.map(Set.keys(x), func(x: Candy) : ValueShared { CandyToValue(x)}))); + }; + case(#ValueMap(x)) { + #Array(Iter.toArray(Iter.map<(Candy,Candy),ValueShared>(Map.entries(x), func(x: (Candy,Candy)) : ValueShared { #Array([CandyToValue(x.0), CandyToValue(x.1)])}))); + }; + //case(_){assert(false);/*unreachable*/#Nat(0);}; + }; + + + }; +} diff --git a/src/icrc16/conversion.mo b/src/icrc16/conversion.mo new file mode 100644 index 0000000..66c2aac --- /dev/null +++ b/src/icrc16/conversion.mo @@ -0,0 +1,2638 @@ +/////////////////////////////// +// +// ©2021 @aramakme +// +//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +// +//The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////// + +/// Conversion utilities for the candy library. +/// +/// This module contains the conversion functions to convert values to & from +/// candy values. + +import Buffer "mo:base/Buffer"; +import Blob "mo:base/Blob"; +import Char "mo:base/Char"; +import Iter "mo:base/Iter"; +import Text "mo:base/Text"; +import HashMap "mo:base/HashMap"; +import Array "mo:base/Array"; +import Nat "mo:base/Nat"; +import Nat16 "mo:base/Nat16"; +import Nat32 "mo:base/Nat32"; +import Nat64 "mo:base/Nat64"; +import Nat8 "mo:base/Nat8"; +import Float "mo:base/Float"; +import Int "mo:base/Int"; +import Int8 "mo:base/Int8"; +import Int16 "mo:base/Int16"; +import Int32 "mo:base/Int32"; +import Int64 "mo:base/Int64"; +import Bool "mo:base/Bool"; +import Principal "mo:base/Principal"; +import Prelude "mo:base/Prelude"; +import Result "mo:base/Result"; +import List "mo:base/List"; +import Types "../types"; +import Hex "mo:encoding_0_4_1/Hex"; +import Properties "../properties"; +import StableBuffer "mo:stablebuffer_1_3_0/StableBuffer"; +import Map "mo:map9/Map"; +import Set "mo:map9/Set"; +import PrincipalExt "mo:principal-ext"; + + +module { + + type CandyShared = Types.CandyShared; + type Candy = Types.Candy; + type ValueShared = Types.ValueShared; + type DataZone = Types.DataZone; + type PropertyShared = Types.PropertyShared; + type Property = Types.Property; + type StableBuffer = StableBuffer.StableBuffer; + + //todo: generic accessors + + /// Convert a `Candy` to `Nat`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int16(15); + /// let converted_value = Conversion.candyToNat(value); + /// ``` + public func candyToNat(val : Candy) : Result.Result { + switch(val){ + case(#Nat(val)){ #ok(val)}; + case(#Nat8(val)){ #ok(Nat8.toNat(val))}; + case(#Nat16(val)){ #ok(Nat16.toNat(val))}; + case(#Nat32(val)){ #ok(Nat32.toNat(val))}; + case(#Nat64(val)){ #ok(Nat64.toNat(val))}; + case(#Float(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){return #err("illegal cast");}; + + #ok(Int.abs(val))}; + case(#Int8(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat(#Int(Int8.toInt(Int8.abs(val))))}; + case(#Int16(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat(#Int(Int16.toInt(Int16.abs(val))))}; + case(#Int32(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat(#Int(Int32.toInt(Int32.abs(val))))}; + case(#Int64(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat(#Int(Int64.toInt(Int64.abs(val))))}; + case(_){return #err("illegal cast");/*unreachable*/}; + }; + }; + + /// Convert a `Candy` to `Nat8`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToNat8(value); + /// ``` + + public func candyToNat8(val : Candy) : Result.Result { + switch(val){ + case(#Nat8(val)){ #ok(val)}; + case(#Nat(val)){ + if(val > Nat8.toNat(Nat8.maximumValue)) return #err("illegal cast"); + #ok(Nat8.fromNat(val)) + }; + case(#Nat16(val)){ + if(Nat16.toNat(val) > Nat8.toNat(Nat8.maximumValue)) return #err("illegal cast"); + #ok(Nat8.fromNat(Nat16.toNat(val)))}; + case(#Nat32(val)){ + if(Nat32.toNat(val) > Nat8.toNat(Nat8.maximumValue)) return #err("illegal cast"); + #ok(Nat8.fromNat(Nat32.toNat(val)))}; + case(#Nat64(val)){ + if(Nat64.toNat(val) > Nat8.toNat(Nat8.maximumValue)) return #err("illegal cast"); + #ok(Nat8.fromNat(Nat64.toNat(val)))}; + case(#Float(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat8(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat8(#Nat(Int.abs(val)))}; + case(#Int8(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat8(#Int(Int8.toInt(Int8.abs(val))))}; + case(#Int16(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat8(#Int(Int16.toInt(Int16.abs(val))))}; + case(#Int32(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat8(#Int(Int32.toInt(Int32.abs(val))))}; + case(#Int64(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat8(#Int(Int64.toInt(Int64.abs(val))))}; + case(_){return #err("illegal cast");/*unreachable*/}; + }; + }; + + /// Convert a `Candy` to `Nat16`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToNat16(value); + /// ``` + + public func candyToNat16(val : Candy) : Result.Result { + switch(val){ + case(#Nat16(val)){ #ok(val)}; + case(#Nat8(val)){ #ok(Nat16.fromNat(Nat8.toNat(val)))}; + case(#Nat(val)){ + //make sure it is less than the largest Nat16 + if(val < Nat16.toNat(Nat16.maximumValue)) { + return #ok(Nat16.fromNat(val)) + } else { + return #err("overflow while converting Nat to Nat16") + } + }; + case(#Nat32(val)){ + if(val < Nat16.toNat32(Nat16.maximumValue)) { + return #ok(Nat16.fromNat(Nat32.toNat(val))) + } else { + return #err("overflow while converting Nat32 to Nat16") + } + }; + case(#Nat64(val)){ + if(Nat64.toNat(val) < Nat16.toNat(Nat16.maximumValue)) { + return #ok(Nat16.fromNat(Nat64.toNat(val))) + } else { + return #err("overflow while converting Nat64 to Nat16") + } + }; + case(#Float(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat16(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat16(#Nat(Int.abs(val)))}; + case(#Int8(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat16(#Int(Int8.toInt(Int8.abs(val))))}; + case(#Int16(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat16(#Int(Int16.toInt(Int16.abs(val))))}; + case(#Int32(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat16(#Int(Int32.toInt(Int32.abs(val))))}; + case(#Int64(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat16(#Int(Int64.toInt(Int64.abs(val))))}; + case(_){return #err("illegal cast");/*unreachable*/}; + }; + }; + + /// Convert a `Candy` to `Nat32`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToNat32(value); + /// ``` + + public func candyToNat32(val : Candy) : Result.Result { + switch(val){ + case(#Nat32(val)){ #ok(val)}; + case(#Nat16(val)){ #ok(Nat32.fromNat(Nat16.toNat(val)))}; + case(#Nat8(val)){ #ok(Nat32.fromNat(Nat8.toNat(val)))}; + case(#Nat(val)){ + if(val < Nat32.toNat(Nat32.maximumValue)) { + return #ok(Nat32.fromNat(val)) + } else { + return #err("overflow while converting Nat to Nat32") + } + }; + case(#Float(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat32(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat32(#Nat(Int.abs(val)))}; + case(#Int8(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat32(#Int(Int8.toInt(Int8.abs(val))))}; + case(#Int16(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat32(#Int(Int16.toInt(Int16.abs(val))))}; + case(#Int32(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat32(#Int(Int32.toInt(Int32.abs(val))))}; + case(#Int64(val)){ + if(val < 0){return #err("illegal cast");}; + candyToNat32(#Int(Int64.toInt(Int64.abs(val))))}; + case(_){return #err("illegal cast");/*unreachable*/}; + }; + }; + + /// Convert a `Candy` to `Nat64`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToNat64(value); + /// ``` + + public func candyToNat64(val : Candy) : Result.Result { + switch(val){ + case(#Nat64(val)){ #ok(val)}; + case(#Nat32(val)){ #ok(Nat64.fromNat(Nat32.toNat(val)))}; + case(#Nat16(val)){ #ok(Nat64.fromNat(Nat16.toNat(val)))}; + case(#Nat8(val)){ #ok(Nat64.fromNat(Nat8.toNat(val)))}; + case(#Nat(val)){ #ok(Nat64.fromNat(val))}; + case(#Float(val)){ + if(val < 0){ return #err("illegal cast"); }; + candyToNat64(#Int(Float.toInt(Float.nearest(val))))}; + case(#Int(val)){ + if(val < 0){ return #err("illegal cast"); }; + candyToNat64(#Nat(Int.abs(val)))}; + case(#Int8(val)){ + if(val < 0){ return #err("illegal cast"); }; + candyToNat64(#Int(Int8.toInt(Int8.abs(val))))}; + case(#Int16(val)){ + if(val < 0){ return #err("illegal cast"); }; + candyToNat64(#Int(Int16.toInt(Int16.abs(val))))}; + case(#Int32(val)){ + if(val < 0){ return #err("illegal cast"); }; + candyToNat64(#Int(Int32.toInt(Int32.abs(val))))}; + case(#Int64(val)){ + if(val < 0){ return #err("illegal cast"); }; + candyToNat64(#Int(Int64.toInt(Int64.abs(val))))}; + case(_){ return #err("illegal cast"); /*unreachable*/ }; + }; + }; + + /// Convert a `Candy` to `Int`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToInt(value); + /// ``` + + public func candyToInt(val : Candy) : Result.Result { + switch(val){ + case(#Int(val)){ #ok(val) }; + case(#Int8(val)){ #ok(Int8.toInt(val)) }; + case(#Int16(val)){ #ok(Int16.toInt(val)) }; + case(#Int32(val)){ #ok(Int32.toInt(val)) }; + case(#Int64(val)){ #ok(Int64.toInt(val)) }; + case(#Nat(val)){ #ok(val) }; + case(#Nat8(val)){ #ok(Nat8.toNat(val)) }; + case(#Nat16(val)){ #ok(Nat16.toNat(val)) }; + case(#Nat32(val)){ #ok(Nat32.toNat(val)) }; + case(#Nat64(val)){ #ok(Nat64.toNat(val)) }; + case(#Float(val)){ #ok(Float.toInt(Float.nearest(val))) }; + case(_){ #err("illegal cast") }; + }; + }; + + /// Convert a `Candy` to `Int8`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToInt8(value); + /// ``` + + public func candyToInt8(val : Candy) : Result.Result { + switch(val){ + case(#Int8(val)){ #ok(val) }; + case(#Int(val)){ + if(val <= Int8.toInt(Int8.maximumValue) and val >= Int8.toInt(Int8.minimumValue)){ + #ok(Int8.fromInt(val)) + } else { + #err("illegal cast") + } + }; + case(#Int16(val)){ + if(Int16.toInt(val) > Int.abs(Int8.toInt(Int8.maximumValue))) return #err("illegal cast"); + #ok(Int8.fromInt(Int16.toInt(val))) }; + case(#Int32(val)){ + if(Int32.toInt(val) > Int.abs(Int8.toInt(Int8.maximumValue))) return #err("illegal cast"); + #ok(Int8.fromInt(Int32.toInt(val))) }; + case(#Int64(val)){ + if(Int64.toInt(val) > Int.abs(Int8.toInt(Int8.maximumValue))) return #err("illegal cast"); + #ok(Int8.fromInt(Int64.toInt(val))) }; + case(#Nat8(val)){ + if(Nat8.toNat(val) > Int.abs(Int8.toInt(Int8.maximumValue))) return #err("illegal cast"); + #ok(Int8.fromNat8(val)) }; + case(#Nat(val)){ + switch(candyToNat8(#Nat(val))){ + case(#ok(nat8)){ #ok(Int8.fromNat8(nat8)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat16(val)){ + switch(candyToNat8(#Nat16(val))){ + case(#ok(nat8)){ #ok(Int8.fromNat8(nat8)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat32(val)){ + switch(candyToNat8(#Nat32(val))){ + case(#ok(nat8)){ #ok(Int8.fromNat8(nat8)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat64(val)){ + switch(candyToNat8(#Nat64(val))){ + case(#ok(nat8)){ #ok(Int8.fromNat8(nat8)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Float(val)){ #ok(Int8.fromInt(Float.toInt(Float.nearest(val)))) }; + case(_){ #err("illegal cast") }; + }; + }; + + /// Convert a `Candy` to `Int16`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToInt16(value); + /// ``` + + public func candyToInt16(val : Candy) : Result.Result { + switch(val){ + case(#Int16(val)){ #ok(val) }; + case(#Int8(val)){ #ok(Int16.fromInt(Int8.toInt(val))) }; + case(#Int(val)){ + if(val <= Int16.toInt(Int16.maximumValue) and val >= Int16.toInt(Int16.minimumValue)){ + #ok(Int16.fromInt(val)) + } else { + #err("illegal cast") + } + }; + case(#Int32(val)){ + if(Int32.toInt(val) > Int.abs(Int16.toInt(Int16.maximumValue))) return #err("illegal cast"); + #ok(Int16.fromInt(Int32.toInt(val))) }; + case(#Int64(val)){ + if(Int64.toInt(val) > Int.abs(Int16.toInt(Int16.maximumValue))) return #err("illegal cast"); + #ok(Int16.fromInt(Int64.toInt(val))) }; + case(#Nat8(val)){ + switch(candyToNat16(#Nat8(val))){ + case(#ok(nat16)){ #ok(Int16.fromNat16(nat16)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat(val)){ + switch(candyToNat16(#Nat(val))){ + case(#ok(nat16)){ #ok(Int16.fromNat16(nat16)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat16(val)){ + if(Nat16.toNat(val) > Int.abs(Int16.toInt(Int16.maximumValue))) return #err("illegal cast"); + #ok(Int16.fromNat16(val)) }; + case(#Nat32(val)){ + switch(candyToNat16(#Nat32(val))){ + case(#ok(nat16)){ #ok(Int16.fromNat16(nat16)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat64(val)){ + switch(candyToNat16(#Nat64(val))){ + case(#ok(nat16)){ #ok(Int16.fromNat16(nat16)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Float(val)){ #ok(Int16.fromInt(Float.toInt(Float.nearest(val)))) }; + case(_){ #err("illegal cast") }; + }; + }; + + /// Convert a `Candy` to `Int32`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToInt32(value); + /// ``` + + public func candyToInt32(val : Candy) : Result.Result { + switch(val){ + case(#Int32(val)){ #ok(val) }; + case(#Int16(val)){ #ok(Int32.fromInt(Int16.toInt(val))) }; + case(#Int8(val)){ #ok(Int32.fromInt(Int8.toInt(val))) }; + case(#Int(val)){ + if(val <= Int32.toInt(Int32.maximumValue) and val >= Int32.toInt(Int32.minimumValue)){ + #ok(Int32.fromInt(val)) + } else { + #err("overflow while converting Int to Int32") + } + }; + case(#Nat8(val)){ + switch(candyToNat32(#Nat8(val))){ + case(#ok(nat32)){ #ok(Int32.fromNat32(nat32)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat(val)){ + switch(candyToNat32(#Nat(val))){ + case(#ok(nat32)){ #ok(Int32.fromNat32(nat32)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat16(val)){ + switch(candyToNat32(#Nat16(val))){ + case(#ok(nat32)){ #ok(Int32.fromNat32(nat32)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat32(val)){ + if(Nat32.toNat(val) > Int.abs(Int32.toInt(Int32.maximumValue))) return #err("illegal cast"); + #ok(Int32.fromNat32(val)) }; + case(#Nat64(val)){ + switch(candyToNat32(#Nat64(val))){ + case(#ok(nat32)){ #ok(Int32.fromNat32(nat32)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Float(val)){ + let nearestVal = Float.toInt(val); + return candyToInt32(#Int(nearestVal)); + }; + case(_){ #err("illegal cast") }; + }; + }; + + /// Convert a `Candy` to `Int64`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToInt64(value); + /// ``` + + public func candyToInt64(val : Candy) : Result.Result { + switch(val){ + case(#Int64(val)){ #ok(val) }; + case(#Int32(val)){ #ok(Int64.fromInt(Int32.toInt(val))) }; + case(#Int16(val)){ #ok(Int64.fromInt(Int16.toInt(val))) }; + case(#Int8(val)){ #ok(Int64.fromInt(Int8.toInt(val))) }; + case(#Int(val)){ + if(val <= Int64.toInt(Int64.maximumValue) and val >= Int64.toInt(Int64.minimumValue)){ + #ok(Int64.fromInt(val)) + } else { + #err("overflow while converting Int to Int64") + } + }; + case(#Nat8(val)){ + switch(candyToNat64(#Nat8(val))){ + case(#ok(nat64)){ #ok(Int64.fromNat64(nat64)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat(val)){ + switch(candyToNat64(#Nat(val))){ + case(#ok(nat64)){ #ok(Int64.fromNat64(nat64)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat16(val)){ + switch(candyToNat64(#Nat16(val))){ + case(#ok(nat64)){ #ok(Int64.fromNat64(nat64)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat32(val)){ + switch(candyToNat64(#Nat32(val))){ + case(#ok(nat64)){ #ok(Int64.fromNat64(nat64)) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat64(val)){ + if(Nat64.toNat(val) > Int.abs(Int64.toInt(Int64.maximumValue))) return #err("illegal cast"); + #ok(Int64.fromNat64(val)) }; + case(#Float(val)){ + let nearestVal = Float.toInt(val); + return candyToInt64(#Int(nearestVal)); + }; + case(_){ #err("illegal cast") }; + }; + }; + + /// Convert a `Candy` to `Float`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int16(2); + /// let converted_value = Conversion.candyToFloat(value); + /// ``` + + public func candyToFloat(val : Candy) : Result.Result { + switch(val){ + case(#Float(val)){ #ok(val) }; + case(#Int64(val)){ #ok(Float.fromInt64(val)) }; + case(#Int32(val)){ + switch(candyToFloat(#Int(Int32.toInt(val)))){ + case(#ok(float)){ #ok(float) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Int16(val)){ + switch(candyToFloat(#Int(Int16.toInt(val)))){ + case(#ok(float)){ #ok(float) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Int8(val)){ + switch(candyToFloat(#Int(Int8.toInt(val)))){ + case(#ok(float)){ #ok(float) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Int(val)){ #ok(Float.fromInt(val)) }; + case(#Nat8(val)){ + switch(candyToFloat(#Int(Nat8.toNat(val)))){ + case(#ok(float)){ #ok(float) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat(val)){ + switch(candyToFloat(#Int(val))){ + case(#ok(float)){ #ok(float) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat16(val)){ + switch(candyToFloat(#Int(Nat16.toNat(val)))){ + case(#ok(float)){ #ok(float) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat32(val)){ + switch(candyToFloat(#Int(Nat32.toNat(val)))){ + case(#ok(float)){ #ok(float) }; + case(#err(e)){ #err(e) }; + } + }; + case(#Nat64(val)){ + switch(candyToFloat(#Int(Nat64.toNat(val)))){ + case(#ok(float)){ #ok(float) }; + case(#err(e)){ #err(e) }; + } + }; + case(_){ #err("illegal cast") }; + }; + }; + + /// Convert a `Candy` to `Text`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Int8(2); + /// let converted_value = Conversion.candyToText(value); + /// ``` + public func candyToText(val : Candy) : Result.Result { + switch(val){ + case(#Text(val)){ #ok(val)}; + case(#Nat64(val)){ #ok(Nat64.toText(val))}; + case(#Nat32(val)){ #ok(Nat32.toText(val))}; + case(#Nat16(val)){ #ok(Nat16.toText(val))}; + case(#Nat8(val)){ #ok(Nat8.toText(val))}; + case(#Nat(val)){ #ok(Nat.toText(val))}; + case(#Int64(val)){ #ok(Int64.toText(val))}; + case(#Int32(val)){ #ok(Int32.toText(val))}; + case(#Int16(val)){ #ok(Int16.toText(val))}; + case(#Int8(val)){ #ok(Int8.toText(val))}; + case(#Int(val)){ #ok(Int.toText(val))}; + case(#Bool(val)){ #ok(Bool.toText(val))}; + case(#Float(val)){ #ok(Float.format(#exact, val))}; + case(#Option(val)){ + switch(val){ + case(null){ #ok("null")}; + case(?val){ + switch(candyToText(val)){ + case(#ok(text)){ #ok(text) }; + case(#err(e)){ #err(e) }; + } + }; + }; + }; + //blob + case(#Blob(val)){ + #ok(Hex.encode(Blob.toArray(val))); + }; + //class + case(#Class(val)){ + var t = "{"; + for(thisItem in Map.entries(val)){ + switch(candyToText(thisItem.1.value)){ + case(#ok(text)){ + t := t # thisItem.1.name # ":" # (if(thisItem.1.immutable == false){"var "}else{""}) # text # "; "; + }; + case(#err(e)){ return #err(e) }; + } + }; + #ok(Text.trimEnd(t, #text(" ")) # "}"); + }; + //principal + case(#Principal(val)){ #ok(Principal.toText(val))}; + //array + case(#Array(val)){ + var t = "["; + for(thisItem in StableBuffer.vals(val)){ + switch(candyToText(thisItem)){ + case(#ok(text)){ + t := t # "{" # text # "} "; + }; + case(#err(e)){ return #err(e) }; + } + }; + #ok(Text.trimEnd(t, #text(" ")) # "]"); + }; + //floats + case(#Floats(val)){ + var t = "["; + for(thisItem in StableBuffer.vals(val)){ + t := t # Float.format(#exact, thisItem) # " "; + }; + #ok(Text.trimEnd(t, #text(" ")) # "]"); + }; + //nats + case(#Nats(val)){ + var t = "["; + for(thisItem in StableBuffer.vals(val)){ + t := t # Nat.toText(thisItem) # " "; + }; + #ok(Text.trimEnd(t, #text(" ")) # "]"); + }; + //ints + case(#Ints(val)){ + var t = "["; + for(thisItem in StableBuffer.vals(val)){ + t := t # Int.toText(thisItem) # " "; + }; + #ok(Text.trimEnd(t, #text(" ")) # "]"); + }; + //bytes + case(#Bytes(val)){ + #ok(Hex.encode(StableBuffer.toArray(val))); + }; + case(#Set(val)){ + var t = "["; + for(thisItem in Set.keys(val)){ + switch(candyToText(thisItem)){ + case(#ok(text)){ + t := t # "{" # text # "} "; + }; + case(#err(e)){ return #err(e) }; + } + }; + #ok(Text.trimEnd(t, #text(" ")) # "]"); + }; + case(#Map(val)){ + var t = "{"; + for(thisItem in Map.entries(val)){ + switch(candyToText(thisItem.1)){ + case(#ok(text)){ + t := t # thisItem.0 # ":" # text # "; "; + }; + case(#err(e)){ return #err(e) }; + } + }; + #ok(Text.trimEnd(t, #text(" ")) # "}"); + }; + case(#ValueMap(val)){ + var t = "{"; + for(thisItem in Map.entries(val)){ + switch(candyToText(thisItem.0)){ + case(#ok(keyText)){ + switch(candyToText(thisItem.1)){ + case(#ok(valueText)){ + t := t # keyText # ":" # valueText # "; "; + }; + case(#err(e)){ return #err(e) }; + } + }; + case(#err(e)){ return #err(e) }; + } + }; + #ok(Text.trimEnd(t, #text(" ")) # "}"); + }; + case(_){ #err("illegal cast") }; + }; + }; + + /// Convert a `Candy` to `Principal`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Principal(Principal.fromText("abc")); + /// let converted_value = Conversion.candyToPrincipal(value); + /// ``` + + public func candyToPrincipal(val : Candy) : Result.Result { + switch(val){ + case(#Principal(val)){ #ok(val) }; + case(#Blob(val)){ + //should not throw even for absurd principals + #ok(Principal.fromBlob(val)); + }; + case(#Text(val)){ + + switch(PrincipalExt.fromText(val)){ + case(?principal){ return #ok(principal) }; + case(null){ return #err("invalid principal") }; + }; + }; + case(_){ #err("illegal cast to Principal") }; + }; + }; + + /// Convert a `Candy` to `Bool`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Bool(false); + /// let converted_value = Conversion.candyToPBool(value); + /// ``` + + public func candyToBool(val : Candy) : Result.Result { + switch(val){ + case(#Bool(val)){ #ok(val) }; + case(#Text(val)){ + if(val == "true"){ return #ok(true) }; + if(val == "false"){ return #ok(false) }; + #err("illegal cast to Bool"); + }; + case(_){ #err("illegal cast to Bool") }; + }; + }; + + /// Convert a `Candy` to `Blob`. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Principal(Principal.fromText("abc")); + /// let converted_value = Conversion.candyToBlob(value); + /// ``` + public func candyToBlob(val : Candy) : Result.Result { + switch(val){ + case(#Blob(val)){ #ok(val) }; + case(#Bytes(val)){ #ok(Blob.fromArray(StableBuffer.toArray(val))) }; + case(#Text(val)){ #ok(Blob.fromArray(textToBytes(val))) }; + case(#Int(val)){ #ok(Blob.fromArray(intToBytes(val))) }; + case(#Nat(val)){ #ok(Blob.fromArray(natToBytes(val))) }; + case(#Nat8(val)){ #ok(Blob.fromArray([val])) }; + case(#Nat16(val)){ #ok(Blob.fromArray(nat16ToBytes(val))) }; + case(#Nat32(val)){ #ok(Blob.fromArray(nat32ToBytes(val))) }; + case(#Nat64(val)){ #ok(Blob.fromArray(nat64ToBytes(val))) }; + case(#Principal(val)){ #ok(Principal.toBlob(val)) }; + case(_){ #err("illegal cast to Blob") }; + }; + }; + + /// Convert a `Candy` to `[Candy]` + /// + /// The conversion is done by getting the array of candy values of the #Array. + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Array([1, 2, 3]); + /// let converted_value = Conversion.candyToValueArray(value); + /// ``` + + public func candyToValueArray(val : Candy) : Result.Result<[Candy], Text> { + switch(val){ + case(#Array(val)){ #ok(StableBuffer.toArray(val)) }; + case(_){ #err("illegal cast to [Candy]") }; + }; + }; + + /// Convert a `Candy` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Principal(Principal.fromText("abc")); + /// let value_as_bytes = Conversion.candyToBytes(value); + /// ``` + public func candyToBytes(val : Candy) : Result.Result<[Nat8], Text> { + switch(val){ + case(#Int(val)){ #ok(intToBytes(val)) }; + case(#Int8(val)){ + switch (candyToInt(#Int8(val))) { + case (#ok(intVal)) { candyToBytes(#Int(intVal)) }; + case (#err(e)) { return #err(e) }; + } + }; + case(#Int16(val)){ + switch (candyToInt(#Int16(val))) { + case (#ok(intVal)) { candyToBytes(#Int(intVal)) }; + case (#err(e)) { return #err(e) }; + } + }; + case(#Int32(val)){ + switch (candyToInt(#Int32(val))) { + case (#ok(intVal)) { candyToBytes(#Int(intVal)) }; + case (#err(e)) { return #err(e) }; + } + }; + case(#Int64(val)){ + switch (candyToInt(#Int64(val))) { + case (#ok(intVal)) { candyToBytes(#Int(intVal)) }; + case (#err(e)) { return #err(e) }; + } + }; + case(#Nat(val)){ #ok(natToBytes(val)) }; + case(#Nat8(val)){ #ok([val]) }; + case(#Nat16(val)){ #ok(nat16ToBytes(val)) }; + case(#Nat32(val)){ #ok(nat32ToBytes(val)) }; + case(#Nat64(val)){ #ok(nat64ToBytes(val)) }; + case(#Float(val)){ #err("conversion from Float to Bytes not implemented") }; + case(#Text(val)){ #ok(textToBytes(val)) }; + case(#Bool(val)){ #ok(boolToBytes(val)) }; + case(#Blob(val)){ #ok(Blob.toArray(val)) }; + case(#Class(val)){ #err("conversion from Class to Bytes not implemented") }; + case(#Principal(val)){ #ok(principalToBytes(val)) }; + case(#Option(val)){ #err("conversion from Option to Bytes not implemented") }; + case(#Array(val)){ #err("conversion from Array to Bytes not implemented") }; + case(#Bytes(val)){ #ok(StableBuffer.toArray(val)) }; + case(#Floats(val)){ #err("conversion from Floats to Bytes not implemented") }; + case(#Nats(val)){ #err("conversion from Nats to Bytes not implemented") }; + case(#Ints(val)){ #err("conversion from Ints to Bytes not implemented") }; + case(#ValueMap(val)){ #err("conversion from ValueMap to Bytes not implemented") }; + case(#Map(val)){ #err("conversion from Map to Bytes not implemented") }; + case(#Set(val)){ #err("conversion from Set to Bytes not implemented") }; + } + }; + /// Convert a `Candy` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Principal(Principal.fromText("abc")); + /// let value_as_buffer = Conversion.candyToBytesBuffer(value); + /// ``` + /// + + public func candyToBytesBuffer(val : Candy) : Result.Result, Text> { + switch (val) { + case (#Bytes(val)) { #ok(Buffer.fromArray(StableBuffer.toArray(val))) }; + case (_) { + switch (candyToBytes(val)) { + case (#ok(bytes)) { #ok(toBuffer(bytes)) }; + case (#err(e)) { #err(e) }; + } + }; + }; + }; + + /// Convert a `Candy` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Nat(102); + /// let value_as_floats_buffer = Conversion.candyToFloatsBuffer(value); + /// ``` + + public func candyToFloatsBuffer(val : Candy) : Result.Result, Text> { + switch (val) { + case (#Floats(val)) { #ok(stableBufferToBuffer(val)) }; + case (_) { + switch (candyToFloat(val)) { + case (#ok(float)) { #ok(toBuffer([float])) }; + case (#err(e)) { #err(e) }; + } + }; + }; + }; + + /// Convert a `Candy` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: Candy = #Nat(102); + /// let value_as_nats_buffer = Conversion.candyToNatsBuffer(value); + /// ``` + + public func candyToNatsBuffer(val : Candy) : Result.Result, Text> { + switch (val) { + case (#Nats(val)) { #ok(stableBufferToBuffer(val)) }; + case (_) { + switch (candyToNat(val)) { + case (#ok(nat)) { #ok(toBuffer([nat])) }; + case (#err(e)) { #err(e) }; + } + }; + }; + }; + + /// Convert a `Candy` to `Map` + /// + /// Example: + /// ```motoko include=import + /// let map = Map.new(); + /// Map.put(map, thash, "akey", #Text("value")); + /// let value: Candy = #Map(map); + /// let value_as_nats_buffer = Conversion.candyToMap(value); + /// ``` + + public func candyToMap(val : Candy) : Result.Result, Text> { + switch (val) { + case (#Map(val)) { #ok(val) }; + case (_) { #err("conversion to Map not supported") }; + }; + }; + + /// Example: + /// ```motoko include=import + /// let map = Map.new(); + /// Map.put(map, candyHashTool, #Text("akey"), #Text("value")); + /// let value: Candy = #ValueMapMap(map); + /// let value_as_nats_buffer = Conversion.candyToValueMap(value); + /// ``` + + public func candyToValueMap(val : Candy) : Result.Result, Text> { + switch (val) { + case (#ValueMap(val)) { #ok(val) }; + case (_) { #err("conversion to Map not supported") }; + }; + }; + + /// Example: + /// ```motoko include=import + /// let map = Set.new(); + /// Set.put(map, candyHashTool, #Text("akey")); + /// let value: Candy = #Set(map); + /// let value_as_nats_buffer = Conversion.candyToSet(value); + /// ``` + + public func candyToSet(val : Candy) : Result.Result, Text> { + switch (val) { + case (#Set(val)) { #ok(val) }; + case (_) { #err("conversion to Set not supported") }; + }; + }; + + /// Convert a `Candy` to `Map` + /// + /// Example: + /// ```motoko include=import + /// let map = Map.new(); + /// Map.put(map, thash, "akey", {name="test";value=#Text("value"); immutable=true;); + /// let value: Candy = #Class(map); + /// let value_as_nats_buffer = Conversion.candyToPropertyMap(value); + /// ``` + + public func candyToPropertyMap(val : Candy) : Result.Result, Text> { + switch (val) { + case (#Class(val)) { #ok(val) }; + case (#Map(val)) { + // Convert Map to Map + var propertyMap = Map.new(); + for (entry in Map.entries(val)) { + + ignore Map.put(propertyMap, Map.thash, entry.0, {name=entry.0; value=entry.1; immutable=true}); + + }; + #ok(propertyMap); + }; + case (_) { #err("conversion to Map not supported") }; + }; + }; + + /// Convert a `CandyShared` to `Nat`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int16(15); + /// let converted_value = Conversion.candySharedToNat(value); + /// ``` + + public func candySharedToNat(val : CandyShared) : Result.Result { + switch (val) { + case (#Nat(val)) { #ok(val) }; + case (#Nat8(val)) { #ok(Nat8.toNat(val)) }; + case (#Nat16(val)) { #ok(Nat16.toNat(val)) }; + case (#Nat32(val)) { #ok(Nat32.toNat(val)) }; + case (#Nat64(val)) { #ok(Nat64.toNat(val)) }; + case (#Float(val)) { + if (val < 0) { #err("illegal cast") } + else { candySharedToNat(#Int(Float.toInt(Float.nearest(val)))) }; + }; + case (#Int(val)) { + if (val < 0) { #err("illegal cast") } + else { #ok(Int.abs(val)) }; + }; + case (#Int8(val)) { + if (val < 0) { #err("illegal cast") } + else { candySharedToNat(#Int(Int8.toInt(Int8.abs(val)))) }; + }; + case (#Int16(val)) { + if (val < 0) { #err("illegal cast") } + else { candySharedToNat(#Int(Int16.toInt(Int16.abs(val)))) }; + }; + case (#Int32(val)) { + if (val < 0) { #err("illegal cast") } + else { candySharedToNat(#Int(Int32.toInt(Int32.abs(val)))) }; + }; + case (#Int64(val)) { + if (val < 0) { #err("illegal cast") } + else { candySharedToNat(#Int(Int64.toInt(Int64.abs(val)))) }; + }; + case (_) { #err("illegal cast") }; + }; + }; + + /// Convert a `CandyShared` to `Nat8`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int8(15); + /// let converted_value = Conversion.candySharedToNat8(value); + /// ``` + + public func candySharedToNat8(val : CandyShared) : Result.Result { + switch(val){ + case(#Nat8(val)){ #ok(val) }; + case(#Nat(val)){ + if(val > Nat8.toNat(Nat8.maximumValue)){ + return #err("overflow while converting Nat to Nat8"); + }; + #ok(Nat8.fromNat(val)) + }; + case(#Nat16(val)){ + if(Nat16.toNat(val) > Nat8.toNat(Nat8.maximumValue)){ + return #err("overflow while converting Nat16 to Nat8"); + } else { + #ok(Nat8.fromNat(Nat16.toNat(val))) + } + }; + case(#Nat32(val)){ + if(Nat32.toNat(val) > Nat8.toNat(Nat8.maximumValue)){ + return #err("overflow while converting Nat32 to Nat8"); + } else { + #ok(Nat8.fromNat(Nat32.toNat(val))) + } + }; + case(#Nat64(val)){ + if(Nat64.toNat(val) > Nat8.toNat(Nat8.maximumValue)){ + return #err("overflow while converting Nat64 to Nat8"); + } else { + #ok(Nat8.fromNat(Nat64.toNat(val))) + } + }; + case(#Float(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat8(#Int(Float.toInt(Float.nearest(val)))) }; + }; + case(#Int(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat8(#Nat(Int.abs(val))) }; + }; + case(#Int8(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat8(#Int(Int8.toInt(Int8.abs(val)))) }; + }; + case(#Int16(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat8(#Int(Int16.toInt(Int16.abs(val)))) }; + }; + case(#Int32(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat8(#Int(Int32.toInt(Int32.abs(val)))) }; + }; + case(#Int64(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat8(#Int(Int64.toInt(Int64.abs(val)))) }; + }; + case(_){ #err("illegal cast") }; + }; + }; + + /// Convert a `CandyShared` to `Nat16`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int16(15); + /// let converted_value = Conversion.candySharedToNat16(value); + /// ``` + + public func candySharedToNat16(val : CandyShared) : Result.Result { + switch(val){ + case(#Nat16(val)){ #ok(val) }; + case(#Nat8(val)){ #ok(Nat16.fromNat(Nat8.toNat(val))) }; + case(#Nat(val)){ + if (val <= Nat16.toNat(Nat16.maximumValue)) { + #ok(Nat16.fromNat(val)) + } else { + #err("overflow while converting Nat to Nat16") + } + }; + case(#Nat32(val)){ + if (Nat32.toNat(val) <= Nat16.toNat(Nat16.maximumValue)) { + #ok(Nat16.fromNat(Nat32.toNat(val))) + } else { + #err("overflow while converting Nat32 to Nat16") + } + }; + case(#Nat64(val)){ + if (Nat64.toNat(val) <= Nat16.toNat(Nat16.maximumValue)) { + #ok(Nat16.fromNat(Nat64.toNat(val))) + } else { + #err("overflow while converting Nat64 to Nat16") + } + }; + case(#Float(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat16(#Int(Float.toInt(Float.nearest(val)))) }; + }; + case(#Int(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat16(#Nat(Int.abs(val))) }; + }; + case(#Int8(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat16(#Int(Int8.toInt(Int8.abs(val)))) }; + }; + case(#Int16(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat16(#Int(Int16.toInt(Int16.abs(val)))) }; + }; + case(#Int32(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat16(#Int(Int32.toInt(Int32.abs(val)))) }; + }; + case(#Int64(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat16(#Int(Int64.toInt(Int64.abs(val)))) }; + }; + case(_){ #err("illegal cast") }; + }; + }; + + /// Convert a `CandyShared` to `Nat32`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int32(15); + /// let converted_value = Conversion.candySharedToNat(value); + /// ``` + + public func candySharedToNat32(val : CandyShared) : Result.Result { + switch(val){ + case(#Nat32(val)){ #ok(val) }; + case(#Nat16(val)){ #ok(Nat32.fromNat(Nat16.toNat(val))) }; + case(#Nat8(val)){ #ok(Nat32.fromNat(Nat8.toNat(val))) }; + case(#Nat(val)){ + if (val <= Nat32.toNat(Nat32.maximumValue)) { + #ok(Nat32.fromNat(val)) + } else { + #err("overflow while converting Nat to Nat32") + } + }; + case(#Float(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat32(#Int(Float.toInt(Float.nearest(val)))) }; + }; + case(#Int(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat32(#Nat(Int.abs(val))) }; + }; + case(#Int8(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat32(#Int(Int8.toInt(Int8.abs(val)))) }; + }; + case(#Int16(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat32(#Int(Int16.toInt(Int16.abs(val)))) }; + }; + case(#Int32(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat32(#Int(Int32.toInt(Int32.abs(val)))) }; + }; + case(#Int64(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat32(#Int(Int64.toInt(Int64.abs(val)))) }; + }; + case(_){ #err("illegal cast") }; + }; + }; + + /// Convert a `CandyShared` to `Nat64`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int16(15); + /// let converted_value = Conversion.candySharedToNat64(value); + /// ``` + + public func candySharedToNat64(val : CandyShared) : Result.Result { + switch(val){ + case(#Nat64(val)){ #ok(val) }; + case(#Nat32(val)){ #ok(Nat64.fromNat(Nat32.toNat(val))) }; + case(#Nat16(val)){ #ok(Nat64.fromNat(Nat16.toNat(val))) }; + case(#Nat8(val)){ #ok(Nat64.fromNat(Nat8.toNat(val))) }; + case(#Nat(val)){ #ok(Nat64.fromNat(val)) }; + case(#Float(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat64(#Int(Float.toInt(Float.nearest(val)))) }; + }; + case(#Int(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat64(#Nat(Int.abs(val))) }; + }; + case(#Int8(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat64(#Int(Int8.toInt(Int8.abs(val)))) }; + }; + case(#Int16(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat64(#Int(Int16.toInt(Int16.abs(val)))) }; + }; + case(#Int32(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat64(#Int(Int32.toInt(Int32.abs(val)))) }; + }; + case(#Int64(val)){ + if(val < 0){ #err("illegal cast") } + else { candySharedToNat64(#Int(Int64.toInt(Int64.abs(val)))) }; + }; + case(_){ #err("illegal cast") }; + }; + }; + + /// Convert a `CandyShared` to `Int`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int16(15); + /// let converted_value = Conversion.candySharedToInt(value); + /// ``` + + public func candySharedToInt(val : CandyShared) : Result.Result { + switch(val){ + case(#Int(val)){ #ok(val) }; + case(#Int8(val)){ #ok(Int8.toInt(val)) }; + case(#Int16(val)){ #ok(Int16.toInt(val)) }; + case(#Int32(val)){ #ok(Int32.toInt(val)) }; + case(#Int64(val)){ #ok(Int64.toInt(val)) }; + case(#Nat(val)){ #ok(val) }; + case(#Nat8(val)){ #ok(Nat8.toNat(val)) }; + case(#Nat16(val)){ #ok(Nat16.toNat(val)) }; + case(#Nat32(val)){ #ok(Nat32.toNat(val)) }; + case(#Nat64(val)){ #ok(Nat64.toNat(val)) }; + case(#Float(val)){ #ok(Float.toInt(Float.nearest(val))) }; + case(_){ #err("illegal cast to Int") }; + }; + }; + + /// Convert a `CandyShared` to `Int8`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Nat8(11); + /// let converted_value = Conversion.candySharedToInt8(value); + /// ``` + + public func candySharedToInt8(val : CandyShared) : Result.Result { + switch(val){ + case(#Int8(val)){ #ok(val) }; + case(#Int(val)){ + if (val >= Int8.toInt(Int8.minimumValue) and val <= Int8.toInt(Int8.maximumValue)) { + #ok(Int8.fromInt(val)) + } else { + #err("overflow while converting Int to Int8") + } + }; + case(#Int16(val)){ + let intVal = Int16.toInt(val); + if (intVal >= Int8.toInt(Int8.minimumValue) and intVal <= Int8.toInt(Int8.maximumValue)) { + #ok(Int8.fromInt(intVal)) + } else { + #err("overflow while converting Int16 to Int8") + } + }; + case(#Int32(val)){ + let intVal = Int32.toInt(val); + if (intVal >= Int8.toInt(Int8.minimumValue) and intVal <= Int8.toInt(Int8.maximumValue)) { + #ok(Int8.fromInt(intVal)) + } else { + #err("overflow while converting Int32 to Int8") + } + }; + case(#Int64(val)){ + let intVal = Int64.toInt(val); + if (intVal >= Int8.toInt(Int8.minimumValue) and intVal <= Int8.toInt(Int8.maximumValue)) { + #ok(Int8.fromInt(intVal)) + } else { + #err("overflow while converting Int64 to Int8") + } + }; + case(#Nat8(val)){ + if(Nat8.toNat(val) <= Int8.toInt(Int8.maximumValue)){ + #ok(Int8.fromNat8(val)) + } else { + #err("overflow while converting Nat8 to Int8") + } + }; + case(#Nat(val)){ + switch (candySharedToNat8(#Nat(val))) { + case (#ok(nat8)) { #ok(Int8.fromNat8(nat8)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat16(val)){ + switch (candySharedToNat8(#Nat16(val))) { + case (#ok(nat8)) { #ok(Int8.fromNat8(nat8)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat32(val)){ + switch (candySharedToNat8(#Nat32(val))) { + case (#ok(nat8)) { #ok(Int8.fromNat8(nat8)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat64(val)){ + switch (candySharedToNat8(#Nat64(val))) { + case (#ok(nat8)) { #ok(Int8.fromNat8(nat8)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Float(val)){ + let intVal = Float.toInt(Float.nearest(val)); + if (intVal >= Int8.toInt(Int8.minimumValue) and intVal <= Int8.toInt(Int8.maximumValue)) { + #ok(Int8.fromInt(intVal)) + } else { + #err("overflow while converting Float to Int8") + } + }; + + case(_){ #err("illegal cast to Int8") }; + }; + }; + + /// Convert a `CandyShared` to `Int16`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Float(10); + /// let converted_value = Conversion.candySharedToInt16(value); + /// ``` + + public func candySharedToInt16(val : CandyShared) : Result.Result { + switch(val){ + case(#Int16(val)){ #ok(val) }; + case(#Int8(val)){ #ok(Int16.fromInt(Int8.toInt(val))) }; + case(#Int(val)){ + if (val >= Int16.toInt(Int16.minimumValue) and val <= Int16.toInt(Int16.maximumValue)) { + #ok(Int16.fromInt(val)) + } else { + #err("overflow while converting Int to Int16") + } + }; + case(#Int32(val)){ + let intVal = Int32.toInt(val); + if (intVal >= Int16.toInt(Int16.minimumValue) and intVal <= Int16.toInt(Int16.maximumValue)) { + #ok(Int16.fromInt(intVal)) + } else { + #err("overflow while converting Int32 to Int16") + } + }; + case(#Int64(val)){ + let intVal = Int64.toInt(val); + if (intVal >= Int16.toInt(Int16.minimumValue) and intVal <= Int16.toInt(Int16.maximumValue)) { + #ok(Int16.fromInt(intVal)) + } else { + #err("overflow while converting Int64 to Int16") + } + }; + case(#Nat8(val)){ + switch (candySharedToNat16(#Nat8(val))) { + case (#ok(nat16)) { #ok(Int16.fromNat16(nat16)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat(val)){ + switch (candySharedToNat16(#Nat(val))) { + case (#ok(nat16)) { #ok(Int16.fromNat16(nat16)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat16(val)){ + if(Nat16.toNat(val) <= Int16.toInt(Int16.maximumValue)){ + #ok(Int16.fromNat16(val)) + } else { + #err("overflow while converting Nat16 to Int16") + } + }; + case(#Nat32(val)){ + switch (candySharedToNat16(#Nat32(val))) { + case (#ok(nat16)) { #ok(Int16.fromNat16(nat16)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat64(val)){ + switch (candySharedToNat16(#Nat64(val))) { + case (#ok(nat16)) { #ok(Int16.fromNat16(nat16)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Float(val)){ + let intVal = Float.toInt(Float.nearest(val)); + if (intVal >= Int16.toInt(Int16.minimumValue) and intVal <= Int16.toInt(Int16.maximumValue)) { + #ok(Int16.fromInt(intVal)) + } else { + #err("overflow while converting Float to Int16") + } + }; + case(_){ #err("illegal cast to Int16") }; + }; + }; + + /// Convert a `CandyShared` to `Int32`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Nat32(1111); + /// let converted_value = Conversion.candySharedToInt32(value); + /// ``` + + public func candySharedToInt32(val : CandyShared) : Result.Result { + switch(val){ + case(#Int32(val)){ #ok(val) }; + case(#Int16(val)){ #ok(Int32.fromInt(Int16.toInt(val))) }; + case(#Int8(val)){ #ok(Int32.fromInt(Int8.toInt(val))) }; + case(#Int(val)){ + if (val >= Int32.toInt(Int32.minimumValue) and val <= Int32.toInt(Int32.maximumValue)) { + #ok(Int32.fromInt(val)) + } else { + #err("overflow while converting Int to Int32") + } + }; + case(#Nat8(val)){ + switch (candySharedToNat32(#Nat8(val))) { + case (#ok(nat32)) { #ok(Int32.fromNat32(nat32)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat(val)){ + switch (candySharedToNat32(#Nat(val))) { + case (#ok(nat32)) { #ok(Int32.fromNat32(nat32)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat16(val)){ + switch (candySharedToNat32(#Nat16(val))) { + case (#ok(nat32)) { #ok(Int32.fromNat32(nat32)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat32(val)){ + if(Nat32.toNat(val) <= Int32.toInt(Int32.maximumValue)){ + #ok(Int32.fromNat32(val)) + } else { + #err("overflow while converting Nat32 to Int32") + } + }; + case(#Nat64(val)){ + switch (candySharedToNat32(#Nat64(val))) { + case (#ok(nat32)) { #ok(Int32.fromNat32(nat32)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Float(val)){ + let intVal = Float.toInt(Float.nearest(val)); + if (intVal >= Int32.toInt(Int32.minimumValue) and intVal <= Int32.toInt(Int32.maximumValue)) { + #ok(Int32.fromInt(intVal)) + } else { + #err("overflow while converting Float to Int32") + } + }; + case(_){ #err("illegal cast to Int32") }; + }; + }; + + /// Convert a `CandyShared` to `Int64`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Nat64(12345); + /// let converted_value = Conversion.candySharedToInt64(value); + /// ``` + + public func candySharedToInt64(val : CandyShared) : Result.Result { + switch(val){ + case(#Int64(val)){ #ok(val) }; + case(#Int32(val)){ #ok(Int64.fromInt(Int32.toInt(val))) }; + case(#Int16(val)){ #ok(Int64.fromInt(Int16.toInt(val))) }; + case(#Int8(val)){ #ok(Int64.fromInt(Int8.toInt(val))) }; + case(#Int(val)){ + if (val >= Int64.toInt(Int64.minimumValue) and val <= Int64.toInt(Int64.maximumValue)) { + #ok(Int64.fromInt(val)) + } else { + #err("overflow while converting Int to Int64") + } + }; + case(#Nat8(val)){ + switch (candySharedToNat64(#Nat8(val))) { + case (#ok(nat64)) { #ok(Int64.fromNat64(nat64)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat(val)){ + switch (candySharedToNat64(#Nat(val))) { + case (#ok(nat64)) { #ok(Int64.fromNat64(nat64)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat16(val)){ + switch (candySharedToNat64(#Nat16(val))) { + case (#ok(nat64)) { #ok(Int64.fromNat64(nat64)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat32(val)){ + switch (candySharedToNat64(#Nat32(val))) { + case (#ok(nat64)) { #ok(Int64.fromNat64(nat64)) }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat64(val)){ + if(Nat64.toNat(val) > Int64.toInt(Int64.maximumValue)){ + return #err("overflow while converting Nat64 to Int64"); + } + else { + + #ok(Int64.fromNat64(val)) + }; + }; + case(#Float(val)){ + let intVal = Float.toInt(Float.nearest(val)); + if (intVal >= Int64.toInt(Int64.minimumValue) and intVal <= Int64.toInt(Int64.maximumValue)) { + #ok(Int64.fromInt(intVal)) + } else { + #err("overflow while converting Float to Int64") + } + }; + case(_){ #err("illegal cast to Int64") }; + }; + }; + + /// Convert a `CandyShared` to `Float`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int16(11); + /// let converted_value = Conversion.candySharedToFloat(value); + /// ``` + + public func candySharedToFloat(val : CandyShared) : Result.Result { + switch(val){ + case(#Float(val)){ #ok(val) }; + case(#Int64(val)){ #ok(Float.fromInt64(val)) }; + case(#Int32(val)){ candySharedToFloat(#Int(Int32.toInt(val))) }; + case(#Int16(val)){ candySharedToFloat(#Int(Int16.toInt(val))) }; + case(#Int8(val)){ candySharedToFloat(#Int(Int8.toInt(val))) }; + case(#Int(val)){ #ok(Float.fromInt(val)) }; + case(#Nat8(val)){ candySharedToFloat(#Int(Nat8.toNat(val))) }; + case(#Nat(val)){ candySharedToFloat(#Int(val)) }; + case(#Nat16(val)){ candySharedToFloat(#Int(Nat16.toNat(val))) }; + case(#Nat32(val)){ candySharedToFloat(#Int(Nat32.toNat(val))) }; + case(#Nat64(val)){ candySharedToFloat(#Int(Nat64.toNat(val))) }; + case(_){ #err("illegal cast to Float") }; + }; + }; + + /// Convert a `CandyShared` to `Text`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Float(11); + /// let converted_value = Conversion.candySharedToText(value); + /// ``` + public func candySharedToText(val : CandyShared) : Result.Result { + switch(val){ + case(#Text(val)){ #ok(val) }; + case(#Nat64(val)){ #ok(Nat64.toText(val)) }; + case(#Nat32(val)){ #ok(Nat32.toText(val)) }; + case(#Nat16(val)){ #ok(Nat16.toText(val)) }; + case(#Nat8(val)){ #ok(Nat8.toText(val)) }; + case(#Nat(val)){ #ok(Nat.toText(val)) }; + case(#Int64(val)){ #ok(Int64.toText(val)) }; + case(#Int32(val)){ #ok(Int32.toText(val)) }; + case(#Int16(val)){ #ok(Int16.toText(val)) }; + case(#Int8(val)){ #ok(Int8.toText(val)) }; + case(#Int(val)){ #ok(Int.toText(val)) }; + case(#Bool(val)){ #ok(Bool.toText(val)) }; + case(#Float(val)){ #ok(Float.format(#exact, val)) }; + case(#Option(val)){ + switch(val){ + case(null){ #ok("null") }; + case(?val){ candySharedToText(val) }; + }; + }; + case(#Blob(val)){ #ok(Hex.encode(Blob.toArray(val))) }; + case(#Class(val)){ + var t = "{"; + for(thisItem in val.vals()){ + switch(candySharedToText(thisItem.value)){ + case(#ok(text)){ + t := t # thisItem.name # ": " # (if(thisItem.immutable == false){"var "}else{""}) # text # "; "; + }; + case(#err(e)){ return #err(e) }; + } + }; + #ok(Text.trimEnd(t, #text(" ")) # "}"); + }; + case(#Principal(val)){ #ok(Principal.toText(val)) }; + case(#Array(val)){ + var t = "["; + for(thisItem in val.vals()){ + switch(candySharedToText(thisItem)){ + case(#ok(text)){ + t := t # "{" # text # "} "; + }; + case(#err(e)){ return #err(e) }; + } + }; + #ok(Text.trimEnd(t, #text(" ")) # "]"); + }; + case(#Floats(val)){ + var t = "["; + for(thisItem in val.vals()){ + t := t # Float.format(#exact, thisItem) # " "; + }; + #ok(Text.trimEnd(t, #text(" ")) # "]"); + }; + case(#Nats(val)){ + var t = "["; + for(thisItem in val.vals()){ + t := t # Nat.toText(thisItem) # " "; + }; + #ok(Text.trimEnd(t, #text(" ")) # "]"); + }; + case(#Ints(val)){ + var t = "["; + for(thisItem in val.vals()){ + t := t # Int.toText(thisItem) # " "; + }; + #ok(Text.trimEnd(t, #text(" ")) # "]"); + }; + case(#Bytes(val)){ #ok(Hex.encode(val)) }; + case(#Set(val)){ + var t = "["; + for(thisItem in val.vals()){ + switch(candySharedToText(thisItem)){ + case(#ok(text)){ + t := t # "{" # text # "} "; + }; + case(#err(e)){ return #err(e) }; + } + }; + #ok(Text.trimEnd(t, #text(" ")) # "]"); + }; + case(#Map(val)){ + var t = "{"; + for(thisItem in val.vals()){ + switch(candySharedToText(thisItem.1)){ + case(#ok(text)){ + t := t # thisItem.0 # ": " # text # "; "; + }; + case(#err(e)){ return #err(e) }; + } + }; + #ok(Text.trimEnd(t, #text(" ")) # "}"); + }; + case(#ValueMap(val)){ + var t = "{"; + for(thisItem in val.vals()){ + switch(candySharedToText(thisItem.0)){ + case(#ok(keyText)){ + switch(candySharedToText(thisItem.1)){ + case(#ok(valueText)){ + t := t # keyText # ": " # valueText # "; "; + }; + case(#err(e)){ return #err(e) }; + } + }; + case(#err(e)){ return #err(e) }; + } + }; + #ok(Text.trimEnd(t, #text(" ")) # "}"); + }; + case(_){ #err("illegal cast to Text") }; + }; + }; + + /// Convert a `CandyShared` to `Principal`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Principal(Principal.fromText("abc")); + /// let converted_value = Conversion.candySharedToPrincipal(value); + /// ``` + + public func candySharedToPrincipal(val : CandyShared) : Result.Result { + switch(val){ + case(#Principal(val)){ #ok(val) }; + case(#Text(val)){ + switch(PrincipalExt.fromText(val)){ + case(?principal){ return #ok(principal) }; + case(null){ return #err("invalid principal") }; + } + }; + case(#Blob(val)){ + #ok(Principal.fromBlob(val)); + }; + case(_){ #err("illegal cast to Principal") }; + }; + }; + + /// Convert a `CandyShared` to `Bool`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Bool(true); + /// let converted_value = Conversion.candySharedToBool(value); + /// ``` + + public func candySharedToBool(val : CandyShared) : Result.Result { + switch(val){ + case(#Bool(val)){ #ok(val) }; + case(#Text(val)){ + switch (Text.trimEnd(val, #text(" "))) { + case("true"){ #ok(true) }; + case("false"){ #ok(false) }; + case(_){ #err("illegal cast to Bool") }; + } + }; + case(_){ #err("illegal cast to Bool") }; + }; + }; + + /// Convert a `CandyShared` to `Blob`. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Principal(Principal.fromText("abc")); + /// let converted_value = Conversion.candySharedToBlob(value); + /// ``` + public func candySharedToBlob(val : CandyShared) : Result.Result { + switch(val){ + case(#Blob(val)){ #ok(val) }; + case(#Bytes(val)){ #ok(Blob.fromArray(val)) }; + case(#Text(val)){ #ok(Blob.fromArray(textToBytes(val))) }; + case(#Int(val)){ #ok(Blob.fromArray(intToBytes(val))) }; + case(#Nat(val)){ #ok(Blob.fromArray(natToBytes(val))) }; + case(#Nat8(val)){ #ok(Blob.fromArray([val])) }; + case(#Nat16(val)){ #ok(Blob.fromArray(nat16ToBytes(val))) }; + case(#Nat32(val)){ #ok(Blob.fromArray(nat32ToBytes(val))) }; + case(#Nat64(val)){ #ok(Blob.fromArray(nat64ToBytes(val))) }; + case(#Principal(val)){ #ok(Principal.toBlob(val)) }; + case(_){ #err("illegal cast to Blob") }; + }; + }; + + /// Convert a `CandyShared` to `[CandyShared]` + /// + /// The conversion is done by getting the array of candy values of the #Array. + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Array([1, 2, 3]); + /// let converted_value = Conversion.candySharedToValueArray(value); + /// ``` + + public func candySharedToValueArray(val : CandyShared) : Result.Result<[CandyShared], Text> { + switch(val){ + case(#Array(val)){ #ok(val) }; + case(_){ #err("illegal cast to [CandyShared]") }; + }; + }; + + /// Convert a `CandyShared` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Principal(Principal.fromText("abc")); + /// let value_as_bytes = Conversion.candySharedToBytes(value); + /// ``` + public func candySharedToBytes(val : CandyShared) : Result.Result<[Nat8], Text> { + switch(val){ + case(#Int(val)){ + #ok(intToBytes(val)); + }; + case(#Int8(val)){ + switch (candySharedToInt(#Int8(val))) { + case (#ok(intVal)) { + #ok(intToBytes(intVal)); + }; + case (#err(e)) { #err(e) }; + } + }; + case(#Int16(val)){ + switch (candySharedToInt(#Int16(val))) { + case (#ok(intVal)) { + #ok(intToBytes(intVal)); + }; + case (#err(e)) { #err(e) }; + } + }; + case(#Int32(val)){ + switch (candySharedToInt(#Int32(val))) { + case (#ok(intVal)) { + #ok(intToBytes(intVal)); + }; + case (#err(e)) { #err(e) }; + } + }; + case(#Int64(val)){ + switch (candySharedToInt(#Int64(val))) { + case (#ok(intVal)) { + #ok(intToBytes(intVal)); + }; + case (#err(e)) { #err(e) }; + } + }; + case(#Nat(val)){ + #ok(natToBytes(val)) + }; + case(#Nat8(val)){ #ok([val]) }; + case(#Nat16(val)){ + #ok(nat16ToBytes(val)) + }; + case(#Nat32(val)){ + #ok(nat32ToBytes(val)) + }; + case(#Nat64(val)){ + #ok(nat64ToBytes(val)) + }; + case(#Float(val)){ #err("conversion from Float to Bytes not implemented") }; + case(#Text(val)){ + #ok(textToBytes(val)) + }; + case(#Bool(val)){ + #ok(boolToBytes(val)) + }; + case(#Blob(val)){ #ok(Blob.toArray(val)) }; + case(#Class(val)){ #err("conversion from Class to Bytes not implemented") }; + case(#Principal(val)){ + #ok(principalToBytes(val)) + }; + case(#Option(val)){ #err("conversion from Option to Bytes not implemented") }; + case(#Array(val)){ #err("conversion from Array to Bytes not implemented") }; + case(#Bytes(val)){ #ok(val) }; + case(#Floats(val)){ #err("conversion from Floats to Bytes not implemented") }; + case(#Nats(val)){ #err("conversion from Nats to Bytes not implemented") }; + case(#Ints(val)){ #err("conversion from Ints to Bytes not implemented") }; + case(#ValueMap(val)){ #err("conversion from ValueMap to Bytes not implemented") }; + case(#Map(val)){ #err("conversion from Map to Bytes not implemented") }; + case(#Set(val)){ #err("conversion from Set to Bytes not implemented") }; + }; + }; + + /// Convert a `CandyShared` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Principal(Principal.fromText("abc")); + /// let value_as_buffer = Conversion.candySharedToBytes(value); + /// ``` + /// + + public func candySharedToBytesBuffer(val : CandyShared) : Result.Result, Text> { + switch (val){ + case(#Bytes(val)){ #ok(toBuffer(val)) }; + case(_){ + switch (candySharedToBytes(val)) { + case (#ok(bytes)) { #ok(toBuffer(bytes)) }; + case (#err(e)) { #err(e) }; + } + }; + }; + }; + + ////////////////////////////////////////////////////////////////////// + // The following functions easily creates a buffer from an arry of any type + ////////////////////////////////////////////////////////////////////// + + /// Create a `Buffer` from [T] where T can be of any type. + /// + /// Example: + /// ```motoko include=import + /// let array = [1, 2, 3]; + /// let buf = Conversion.toBuffer(array); + /// ``` + public func toBuffer(x :[T]) : Buffer.Buffer{ + let thisBuffer = Buffer.Buffer(x.size()); + for(thisItem in x.vals()){ + thisBuffer.add(thisItem); + }; + return thisBuffer; + }; + + /// Create a `Buffer` from `StableBuffer` where T can be of any type. + /// + /// Example: + /// ```motoko include=import + /// let stable_buff = StableBuffer.fromArray([1, 2, 3]); + /// let buff = Conversion.stableBufferToBuffer(stable_buff); + /// ``` + public func stableBufferToBuffer(x : StableBuffer) : Buffer.Buffer{ + let thisBuffer = Buffer.Buffer(StableBuffer.size(x)); + for(thisItem in StableBuffer.vals(x)){ + thisBuffer.add(thisItem); + }; + return thisBuffer; + }; + + /// Convert a `CandyShared` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Nat(102); + /// let value_as_floats_buffer = Conversion.candySharedToFloatsBuffer(value); + /// ``` + + public func candySharedToFloatsBuffer(val : CandyShared) : Result.Result, Text> { + switch (val){ + case(#Floats(val)){ #ok(toBuffer(val)) }; + case(_){ + switch (candySharedToFloat(val)) { + case (#ok(float)) { #ok(toBuffer([float])) }; + case (#err(e)) { #err(e) }; + } + }; + }; + }; + + /// Convert a `CandyShared` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Nat(102); + /// let value_as_nats_buffer = Conversion.candySharedToNatsBuffer(value); + /// ``` + + public func candySharedToNatsBuffer(val : CandyShared) : Result.Result, Text> { + switch (val){ + case(#Nats(val)){ #ok(toBuffer(val)) }; + case(_){ + switch (candySharedToNat(val)) { + case (#ok(nat)) { #ok(toBuffer([nat])) }; + case (#err(e)) { #err(e) }; + } + }; + }; + }; + + /// Convert a `CandyShared` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let value: CandyShared = #Int(102); + /// let value_as_nats_buffer = Conversion.candySharedToIntsBuffer(value); + /// ``` + + public func candySharedToIntsBuffer(val : CandyShared) : Result.Result, Text> { + switch (val){ + case(#Ints(val)){ #ok(toBuffer(val)) }; + case(_){ + switch (candySharedToInt(val)) { + case (#ok(int)) { #ok(toBuffer([int])) }; + case (#err(e)) { #err(e) }; + } + }; + }; + }; + + /// Convert `Candy` to `Properties` + /// + /// Example: + /// ```motoko include=import + /// let val: Candy = #Class([ + /// { + /// name = "prop1"; + /// value = #Principal(Principal.fromText("abc")); + /// immutable = true; + /// }, + /// { + /// name = "prop2"; + /// value = #Principal(Principal.fromText("abc")); + /// immutable = false; + /// } + /// ]); + /// let props = Conversion.candyToProperties(val); + /// ``` + public func candySharedToProperties(val : CandyShared) : Result.Result { + switch(val){ + case(#Class(val)){ #ok(val) }; + case(#Map(val)){ #ok( + Array.map<(Text, Types.CandyShared), Types.PropertyShared>(val, func(a,b){ + { + name = a; + value = b; + immutable = true; // default to true + }; + }))}; + case(_){ #err("illegal cast to PropertiesShared") }; + }; + }; + + /// Convert `[Nat8]` to a `Text` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [140, 145, 190, 192]; + /// let bytes_as_text = Conversion.bytesToText(bytes); + /// ``` + public func bytesToText(_bytes : [Nat8]) : Text{ + var result : Text = ""; + var aChar : [var Nat8] = [var 0, 0, 0, 0]; + + for(thisChar in Iter.range(0,_bytes.size())){ + if(thisChar > 0 and thisChar % 4 == 0){ + aChar[0] := _bytes[thisChar-4]; + aChar[1] := _bytes[thisChar-3]; + aChar[2] := _bytes[thisChar-2]; + aChar[3] := _bytes[thisChar-1]; + switch (bytesToNat32(Array.freeze(aChar))) { + case (#ok(nat32)) { result := result # Char.toText(Char.fromNat32(nat32)); }; + case (#err(e)) { result := result # "�"; }; // Use a placeholder for error cases + }; + }; + }; + return result; + }; + + /// Convert `Principal` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let p = Principal.fromText("xyz"); + /// let principal_as_bytes = Conversion.principalToBytes(p); + /// ``` + public func principalToBytes(_principal: Principal) : [Nat8]{ + return Blob.toArray(Principal.toBlob(_principal)); + }; + + /// Convert Bytes(`[Nat8]`) to `Principal` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [140, 145, 190, 192]; + /// let p = Conversion.bytesToPrincipal(bytes); + /// ``` + public func bytesToPrincipal(_bytes: [Nat8]) : Principal{ + return Principal.fromBlob(Blob.fromArray(_bytes)); + }; + + /// Convert `Principal` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let b = false; + /// let bool_as_bytes = Conversion.boolToBytes(b); + /// ``` + public func boolToBytes(_bool : Bool) : [Nat8]{ + if(_bool == true){ + return [1:Nat8]; + } else { + return [0:Nat8]; + }; + }; + + /// Convert Bytes(`[Nat8]`) to `Bool` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [1:Nat8]; + /// let b = Conversion.bytesToBool(bytes); // true + /// ``` + public func bytesToBool(_bytes : [Nat8]) : Bool{ + if(_bytes.size() == 0){ + return false; // invalid size + }; + if(_bytes[0] == 0){ + return false; + } else { + return true; + }; + }; + + /// Convert `Int` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let i = 266; + /// let int_as_bytes = Conversion.intToBytes(b); // [0, 2, 10] + /// ``` + public func intToBytes(n : Int) : [Nat8]{ + var a : Nat8 = 0; + var c : Nat8 = if(n < 0){1}else{0}; + var b : Nat = Int.abs(n); + var bytes = List.nil(); + var test = true; + while test { + a := Nat8.fromNat(b % 128); + b := b / 128; + bytes := List.push(a, bytes); + test := b > 0; + }; + let result = toBuffer([c]); + result.append(toBuffer(List.toArray(bytes))); + Buffer.toArray(result); + //Array.append([c],List.toArray(bytes)); + }; + + /// Convert Bytes(`[Nat8]`) to `Int` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [0, 2, 10]; + /// let b = Conversion.bytesToBool(bytes); // 266 + /// ``` + public func bytesToInt(_bytes : [Nat8]) : Result.Result { + if (_bytes.size() < 1) { + return #err("Invalid byte array size for conversion to Int"); + }; + + if (_bytes.size()==1 and _bytes[0] == 0) { + return #ok(0); // special case for single byte zero + }; + + if (_bytes.size() < 2) { + return #err("Invalid byte array size for conversion to Int"); + }; + + var n : Int = 0; + var i = 0; + let natBytes = Array.tabulate(_bytes.size() - 1, func(idx) { _bytes[idx + 1] }); + + Array.foldRight(natBytes, (), func(byte, _) { + n += Nat8.toNat(byte) * (128 ** i); + i += 1; + return; + }); + + if (_bytes[0] == 1) { + n *= -1; + }; + + return #ok(n); + }; + + /// Unwrap an Option value. + /// + /// If the underlying value is a #Option(T), T is returned, + /// Otherwise, the parameter is returned as it is. + /// + /// Example: + /// ```motoko include=import + /// let val: Candy = #Option(?#Principal(Principal.fromText("xyz"))); + /// let unwrapped_val = Conversion.unwrapOptionCandy(val); + /// ``` + public func unwrapOptionCandy(val : Candy): Result.Result { + switch(val){ + case(#Option(val)){ + switch(val){ + case(null){ + #err("option is null"); + }; + case(?val){ + #ok(val); + } + }; + }; + case(otherVal){ return(#ok(val)) }; + }; + }; + + /// Unwrap an Option value. + /// + /// If the underlying value is a #Option(T), T is returned, + /// Otherwise, the parameter is returned as it is. + /// + /// Example: + /// ```motoko include=import + /// let val: CandyShared = #Option(?#Principal(Principal.fromText("xyz"))); + /// let unwrapped_val = Conversion.unwrapOptionCandy(val); + /// ``` + public func unwrapOptionCandyShared(val : CandyShared): Result.Result { + switch(val){ + case(#Option(val)){ + switch(val){ + case(null){ + #err("option is null"); + }; + case(?val){ + #ok(val); + } + }; + }; + case(otherVal){ #ok(val) }; + }; + }; + + ///converts a candyshared value to the reduced set of ValueShared used in many places like ICRC3. Some types not recoverable + public func candySharedToValue(x: CandyShared) : ValueShared { + switch(x){ + case(#Text(x)) #Text(x); + case(#Map(x)) { + let buf = Buffer.Buffer<(Text, ValueShared)>(1); + for(thisItem in x.vals()){ + buf.add((thisItem.0, candySharedToValue(thisItem.1))); + }; + #Map(Buffer.toArray(buf)); + }; + case(#Class(x)) { + let buf = Buffer.Buffer<(Text, ValueShared)>(1); + for(thisItem in x.vals()){ + buf.add((thisItem.name, candySharedToValue(thisItem.value))); + }; + #Map(Buffer.toArray(buf)); + }; + case(#Int(x)) #Int(x); + case(#Int8(x)) #Int(Int8.toInt(x)); + case(#Int16(x)) #Int(Int16.toInt(x)); + case(#Int32(x)) #Int(Int32.toInt(x)); + case(#Int64(x)) #Int(Int64.toInt(x)); + case(#Ints(x)){ + #Array(Array.map(x, func(x: Int) : ValueShared { #Int(x)})); + }; + case(#Nat(x)) #Nat(x); + case(#Nat8(x)) #Nat(Nat8.toNat(x)); + case(#Nat16(x)) #Nat(Nat16.toNat(x)); + case(#Nat32(x)) #Nat(Nat32.toNat(x)); + case(#Nat64(x)) #Nat(Nat64.toNat(x)); + case(#Nats(x)){ + #Array(Array.map(x, func(x: Nat) : ValueShared { #Nat(x)})); + }; + case(#Bytes(x)){ + #Blob(Blob.fromArray(x)); + }; + case(#Array(x)) { + #Array(Array.map(x, candySharedToValue)); + }; + case(#Blob(x)) #Blob(x); + case(#Bool(x)) #Blob(Blob.fromArray([if(x==true){1 : Nat8} else {0: Nat8}])); + case(#Float(x)){#Text(Float.format(#exact, x))}; + case(#Floats(x)){ + #Array(Array.map(x, func(x: Float) : ValueShared { candySharedToValue(#Float(x))})); + }; + case(#Option(x)){ //empty array is null + switch(x){ + case(null) #Array([]); + case(?x) #Array([candySharedToValue(x)]); + }; + }; + case(#Principal(x)){ + #Blob(Principal.toBlob(x)); + }; + case(#Set(x)) { + #Array(Array.map(x, func(x: CandyShared) : ValueShared { candySharedToValue(x)})); + }; + case(#ValueMap(x)) { + #Array(Array.map<(CandyShared,CandyShared),ValueShared>(x, func(x: (CandyShared,CandyShared)) : ValueShared { #Array([candySharedToValue(x.0), candySharedToValue(x.1)])})); + }; + //case(_){assert(false);/*unreachable*/#Nat(0);}; + }; + + + }; + + ///converts a candy value to the reduced set of ValueShared used in many places like ICRC3. Some types not recoverable + public func candyToValue(x: Candy) : ValueShared { + switch(x){ + case(#Text(x)) #Text(x); + case(#Map(x)) { + let buf = Buffer.Buffer<(Text, ValueShared)>(1); + for(thisItem in Map.entries(x)){ + buf.add((thisItem.0, candyToValue(thisItem.1))); + }; + #Map(Buffer.toArray(buf)); + }; + case(#Class(x)) { + let buf = Buffer.Buffer<(Text, ValueShared)>(1); + for(thisItem in Map.entries(x)){ + buf.add((thisItem.1.name, candyToValue(thisItem.1.value))); + }; + #Map(Buffer.toArray(buf)); + }; + case(#Int(x)) #Int(x); + case(#Int8(x)) #Int(Int8.toInt(x)); + case(#Int16(x)) #Int(Int16.toInt(x)); + case(#Int32(x)) #Int(Int32.toInt(x)); + case(#Int64(x)) #Int(Int64.toInt(x)); + case(#Ints(x)){ + #Array(StableBuffer.toArray(StableBuffer.map(x, func(x: Int) : ValueShared { #Int(x)}))); + }; + case(#Nat(x)) #Nat(x); + case(#Nat8(x)) #Nat(Nat8.toNat(x)); + case(#Nat16(x)) #Nat(Nat16.toNat(x)); + case(#Nat32(x)) #Nat(Nat32.toNat(x)); + case(#Nat64(x)) #Nat(Nat64.toNat(x)); + case(#Nats(x)){ + #Array(StableBuffer.toArray(StableBuffer.map(x, func(x: Nat) : ValueShared { #Nat(x)}))); + }; + case(#Bytes(x)){ + #Blob(Blob.fromArray(StableBuffer.toArray(x))); + }; + case(#Array(x)) { + #Array(StableBuffer.toArray(StableBuffer.map(x, candyToValue))); + }; + case(#Blob(x)) #Blob(x); + case(#Bool(x)) #Blob(Blob.fromArray([if(x==true){1 : Nat8} else {0: Nat8}])); + case(#Float(x)){#Text(Float.format(#exact, x))}; + case(#Floats(x)){ + #Array(StableBuffer.toArray(StableBuffer.map(x, func(x: Float) : ValueShared { candyToValue(#Float(x))}))); + }; + case(#Option(x)){ //empty array is null + switch(x){ + case(null) #Array([]); + case(?x) #Array([candyToValue(x)]); + }; + }; + case(#Principal(x)){ + #Blob(Principal.toBlob(x)); + }; + case(#Set(x)) { + #Array(Iter.toArray(Iter.map(Set.keys(x), func(x: Candy) : ValueShared { candyToValue(x)}))); + }; + case(#ValueMap(x)) { + #Array(Iter.toArray(Iter.map<(Candy,Candy),ValueShared>(Map.entries(x), func(x: (Candy,Candy)) : ValueShared { #Array([candyToValue(x.0), candyToValue(x.1)])}))); + }; + //case(_){assert(false);/*unreachable*/#Nat(0);}; + }; + + + + + }; + + ////////////////////////////////////////////////////////////////////// + // The following functions convert standard types to Byte arrays + // From there you can easily get to blobs if necessary with the Blob package + ////////////////////////////////////////////////////////////////////// + + /// Convert a `Nat` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let value: Nat = 150; + /// let bytes = Conversion.natToBytes(value); + /// ``` + public func natToBytes(n : Nat) : [Nat8] { + var a : Nat8 = 0; + var b : Nat = n; + var bytes = List.nil(); + var test = true; + while test { + a := Nat8.fromNat(b % 256); + b := b / 256; + bytes := List.push(a, bytes); + test := b > 0; + }; + List.toArray(bytes); + }; + + /// Convert a `Nat64` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let value: Nat64 = 150; + /// let bytes = Conversion.nat64ToBytes(value); + /// ``` + public func nat64ToBytes(x : Nat64) : [Nat8] { + [ Nat8.fromNat(Nat64.toNat((x >> 56) & (255))), + Nat8.fromNat(Nat64.toNat((x >> 48) & (255))), + Nat8.fromNat(Nat64.toNat((x >> 40) & (255))), + Nat8.fromNat(Nat64.toNat((x >> 32) & (255))), + Nat8.fromNat(Nat64.toNat((x >> 24) & (255))), + Nat8.fromNat(Nat64.toNat((x >> 16) & (255))), + Nat8.fromNat(Nat64.toNat((x >> 8) & (255))), + Nat8.fromNat(Nat64.toNat((x & 255))) ]; + }; + + /// Convert a `Nat32` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let value: Nat32 = 150; + /// let bytes = Conversion.nat32ToBytes(value); + /// ``` + public func nat32ToBytes(x : Nat32) : [Nat8] { + [ Nat8.fromNat(Nat32.toNat((x >> 24) & (255))), + Nat8.fromNat(Nat32.toNat((x >> 16) & (255))), + Nat8.fromNat(Nat32.toNat((x >> 8) & (255))), + Nat8.fromNat(Nat32.toNat((x & 255))) ]; + }; + + /// Convert a `Nat16` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let value: Nat16 = 150; + /// let bytes = Conversion.nat16ToBytes(value); + /// ``` + public func nat16ToBytes(x : Nat16) : [Nat8] { + [ Nat8.fromNat(Nat16.toNat((x >> 8) & (255))), + Nat8.fromNat(Nat16.toNat((x & 255))) ]; + }; + + /// Convert Bytes(`[Nat8]`) to `Nat16` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [1, 2, 3, 4]; + /// let value = Conversion.bytesToNat16(bytes); + /// ``` + public func bytesToNat16(bytes: [Nat8]) : Result.Result { + if (bytes.size() < 2) { + // If less than required, use bytesToNat and convert to Nat16 + let natValue = bytesToNat(bytes); + if (natValue <= Nat16.toNat(Nat16.maximumValue)) { + return #ok(Nat16.fromNat(natValue)); + } else { + return #err("overflow while converting bytes to Nat16"); + } + } else if (bytes.size() > 2) { + // If too large, return an error + return #err("too many bytes to convert to Nat16"); + } else { + // If exactly 2 bytes, perform the conversion + return #ok( + (Nat16.fromNat(Nat8.toNat(bytes[0])) << 8) + + (Nat16.fromNat(Nat8.toNat(bytes[1]))) + ); + } + }; + + /// Convert Bytes(`[Nat8]`) to `Nat32` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [1, 2, 3, 4]; + /// let value = Conversion.bytesToNat32(bytes); + /// ``` + public func bytesToNat32(bytes: [Nat8]) : Result.Result { + if (bytes.size() < 4) { + // If less than required, use bytesToNat and convert to Nat32 + let natValue = bytesToNat(bytes); + if (natValue <= Nat32.toNat(Nat32.maximumValue)) { + return #ok(Nat32.fromNat(natValue)); + } else { + return #err("overflow while converting bytes to Nat32"); + } + } else if (bytes.size() > 4) { + // If too large, return an error + return #err("too many bytes to convert to Nat32"); + } else { + // If exactly 4 bytes, perform the conversion + return #ok( + (Nat32.fromNat(Nat8.toNat(bytes[0])) << 24) + + (Nat32.fromNat(Nat8.toNat(bytes[1])) << 16) + + (Nat32.fromNat(Nat8.toNat(bytes[2])) << 8) + + (Nat32.fromNat(Nat8.toNat(bytes[3]))) + ); + } + }; + + /// Convert Bytes(`[Nat8]`) to `Nat64` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [1, 2, 3, 4]; + /// let value = Conversion.bytesToNat64(bytes); + /// ``` + public func bytesToNat64(bytes: [Nat8]) : Result.Result { + if (bytes.size() < 8) { + // If less than required, use bytesToNat and convert to Nat64 + let natValue = bytesToNat(bytes); + if (natValue <= Nat64.toNat(Nat64.maximumValue)) { + return #ok(Nat64.fromNat(natValue)); + } else { + return #err("overflow while converting bytes to Nat64"); + } + } else if (bytes.size() > 8) { + // If too large, return an error + return #err("too many bytes to convert to Nat64"); + } else { + // If exactly 8 bytes, perform the conversion + return #ok( + (Nat64.fromNat(Nat8.toNat(bytes[0])) << 56) + + (Nat64.fromNat(Nat8.toNat(bytes[1])) << 48) + + (Nat64.fromNat(Nat8.toNat(bytes[2])) << 40) + + (Nat64.fromNat(Nat8.toNat(bytes[3])) << 32) + + (Nat64.fromNat(Nat8.toNat(bytes[4])) << 24) + + (Nat64.fromNat(Nat8.toNat(bytes[5])) << 16) + + (Nat64.fromNat(Nat8.toNat(bytes[6])) << 8) + + (Nat64.fromNat(Nat8.toNat(bytes[7]))) + ); + } + }; + + /// Convert Bytes(`[Nat8]`) to `Nat` + /// + /// Example: + /// ```motoko include=import + /// let bytes: [Nat8] = [1, 2, 3, 4]; + /// let value = Conversion.bytesToNat(bytes); + /// ``` + public func bytesToNat(bytes : [Nat8]) : Nat { + if(bytes.size() == 0) { + return 0; // empty array + }; + var n : Nat = 0; + var i = 0; + Array.foldRight(bytes, (), func (byte, _) { + n += Nat8.toNat(byte) * 256 ** i; + i += 1; + return; + }); + return n; + }; + + /// Convert `Text` to `Buffer` + /// + /// Example: + /// ```motoko include=import + /// let t = "sample_text"; + /// let buf = Conversion.textToByteBuffer(t); + /// ``` + public func textToByteBuffer(_text : Text) : Buffer.Buffer{ + let result : Buffer.Buffer = Buffer.Buffer((_text.size() * 4) +4); + for(thisChar in _text.chars()){ + for(thisByte in nat32ToBytes(Char.toNat32(thisChar)).vals()){ + result.add(thisByte); + }; + }; + return result; + }; + + /// Convert `Text` to Bytes(`[Nat8]`) + /// + /// Example: + /// ```motoko include=import + /// let t = "sample_text"; + /// let bytes = Conversion.textToBytes(t); + /// ``` + public func textToBytes(_text : Text) : [Nat8]{ + return Buffer.toArray(textToByteBuffer(_text)); + }; + + /// Encode `Text` to a giant int(`?Nat`) + /// + /// Example: + /// ```motoko include=import + /// let t = "sample_text"; + /// let encoded_t = Conversion.encodeTextAsNat(t); + /// ``` + public func encodeTextAsNat(phrase : Text) : ?Nat { + var theSum : Nat = 0; + Iter.iterate(Text.toIter(phrase), func (x : Char, n : Nat) { + if (x >= '0' and x <= '9') { + theSum := theSum + ((Nat32.toNat(Char.toNat32(x)) - Nat32.toNat(Char.toNat32('0'))) * 10 ** (phrase.size() - n - 1)); + } else { + return; // Ignore non-digit characters + }; + }); + return ?theSum; + }; + + /// Convert `Text` to a `?Nat` + /// + /// Example: + /// ```motoko include=import + /// let t = "100"; + /// let t_as_nat = Conversion.textToNat(t); // 100 + /// ``` + /// + /// Note: Returns `null` if the text is empty. + public func textToNat( txt : Text) : ?Nat { + if(txt.size() > 0){ + let chars = txt.chars(); + var num : Nat = 0; + for (v in chars){ + if (v >= '0' and v <= '9') { + let charToNum = Nat32.toNat(Char.toNat32(v) - Char.toNat32('0')); + num := num * 10 + charToNum; + } else { + return null; + }; + }; + ?num; + }else { + return null; + }; + }; +} diff --git a/test/bool_to_bytes.test.mo b/test/bool_to_bytes.test.mo new file mode 100644 index 0000000..2d96a01 --- /dev/null +++ b/test/bool_to_bytes.test.mo @@ -0,0 +1,21 @@ +import Debug "mo:base/Debug"; +import Conversion "../src/icrc16/conversion"; +import {test} "mo:test"; + + +func testBoolToBytes() { + // Test case 1: Convert true to bytes + let result1 = Conversion.boolToBytes(true); + Debug.print(debug_show(result1)); + assert(result1 == [1]); + + // Test case 2: Convert false to bytes + let result2 = Conversion.boolToBytes(false); + Debug.print(debug_show(result2)); + assert(result2 == [0]); + + Debug.print("All boolToBytes tests passed."); +}; + +test("boolToBytes", testBoolToBytes); + diff --git a/test/bytes_to_bool.test.mo b/test/bytes_to_bool.test.mo new file mode 100644 index 0000000..15aefa5 --- /dev/null +++ b/test/bytes_to_bool.test.mo @@ -0,0 +1,35 @@ +import Debug "mo:base/Debug"; +import Conversion "../src/icrc16/conversion"; +import {test} "mo:test"; + + + func testBytesToBool() { + // Test case 1: Convert bytes [1] to true + let result1 = Conversion.bytesToBool([1]); + Debug.print(debug_show(result1)); + assert(result1 == true); + + // Test case 2: Convert bytes [0] to false + let result2 = Conversion.bytesToBool([0]); + Debug.print(debug_show(result2)); + assert(result2 == false); + + // Test case 3: Invalid bytes input (empty array) + let result3 = Conversion.bytesToBool([]); + + //Debug.print(debug_show(result3)); + assert(result3 == false); // Assuming empty input returns false + + // Test case 4: Invalid bytes input (array with multiple elements) + let result4 = Conversion.bytesToBool([1, 0]); + + //Debug.print(debug_show(result4)); + assert(result4); + + Debug.print("All bytesToBool tests passed."); + }; + + test("testBytesToBool", testBytesToBool); + + + diff --git a/test/conversion.test.mo b/test/conversion.test.mo new file mode 100644 index 0000000..56bf67c --- /dev/null +++ b/test/conversion.test.mo @@ -0,0 +1,2672 @@ +import Debug "mo:base/Debug"; +import Result "mo:base/Result"; +import Conversion "../src/icrc16/conversion"; +import Types "../src/types"; +import StableBuffer "mo:stablebuffer_1_3_0/StableBuffer"; +import Map "mo:map9/Map"; +import Iter "mo:base/Iter"; +import Buffer "mo:base/Buffer"; +import Principal "mo:base/Principal"; +import Blob "mo:base/Blob"; +import Array "mo:base/Array"; +import Set "mo:map9/Set"; +import Error "mo:base/Error"; +import PrincipalExt "mo:principal-ext"; +import {test} "mo:test"; + + + + func testCandyToNat() { + // Test case 1: Valid Nat input + let result1 = Conversion.candyToNat(#Nat(42)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(42)); + + // Test case 2: Valid Nat8 input + let result2 = Conversion.candyToNat(#Nat8(255)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(255)); + + // Test case 3: Valid Float input + let result3 = Conversion.candyToNat(#Float(42.0)); + Debug.print(debug_show(result3)); + assert(result3 == #ok(42)); + + // Test case 4: Negative Float input + let result4 = Conversion.candyToNat(#Float(-42.0)); + Debug.print(debug_show(result4)); + assert(result4 == #err("illegal cast")); + + // Test case 5: Invalid type input + let result5 = Conversion.candyToNat(#Text("invalid")); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Negative Int input + let result6 = Conversion.candyToNat(#Int(-42)); + Debug.print(debug_show(result6)); + assert(result6 == #err("illegal cast")); + + // Test case 7: Valid Int input + let result7 = Conversion.candyToNat(#Int(42)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(42)); + + Debug.print("All candyToNat tests passed."); + }; + test("testCandyToNat", testCandyToNat); + + + func testCandyToNat8() { + // Test case 1: Valid Nat8 input + let result1 = Conversion.candyToNat8(#Nat8(255)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(255)); + + Debug.print("Result of candyToNat8 for Nat8(255): " # debug_show(result1)); + + // Test case 2: Valid Nat input within Nat8 range + let result2 = Conversion.candyToNat8(#Nat(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(42)); + + // Test case 3: Nat input exceeding Nat8 range + let result3 = Conversion.candyToNat8(#Nat(300)); + Debug.print(debug_show(result3)); + assert(result3 == #err("illegal cast")); + + // Test case 4: Valid Float input within Nat8 range + let result4 = Conversion.candyToNat8(#Float(42.0)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(42)); + + // Test case 5: Negative Float input + let result5 = Conversion.candyToNat8(#Float(-42.0)); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Invalid type input + let result6 = Conversion.candyToNat8(#Text("invalid")); + Debug.print(debug_show(result6)); + assert(result6 == #err("illegal cast")); + + // Test case 7: Negative Int input + let result7 = Conversion.candyToNat8(#Int(-42)); + Debug.print(debug_show(result7)); + assert(result7 == #err("illegal cast")); + + // Test case 8: Valid Int input within Nat8 range + let result8 = Conversion.candyToNat8(#Int(42)); + Debug.print(debug_show(result8)); + assert(result8 == #ok(42)); + + Debug.print("All candyToNat8 tests passed."); + }; + test("testCandyToNat8", testCandyToNat8); + + func testCandyToNat16() { + // Test case 1: Valid Nat16 input + let result1 = Conversion.candyToNat16(#Nat16(65535)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(65535)); + + // Test case 2: Valid Nat input within Nat16 range + let result2 = Conversion.candyToNat16(#Nat(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(42)); + + // Test case 3: Nat input exceeding Nat16 range + let result3 = Conversion.candyToNat16(#Nat(70000)); + Debug.print(debug_show(result3)); + assert(result3 == #err("overflow while converting Nat to Nat16")); + + // Test case 4: Valid Float input within Nat16 range + let result4 = Conversion.candyToNat16(#Float(42.0)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(42)); + + // Test case 5: Negative Float input + let result5 = Conversion.candyToNat16(#Float(-42.0)); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Invalid type input + let result6 = Conversion.candyToNat16(#Text("invalid")); + Debug.print(debug_show(result6)); + assert(result6 == #err("illegal cast")); + + // Test case 7: Negative Int input + let result7 = Conversion.candyToNat16(#Int(-42)); + Debug.print(debug_show(result7)); + assert(result7 == #err("illegal cast")); + + // Test case 8: Valid Int input within Nat16 range + let result8 = Conversion.candyToNat16(#Int(42)); + Debug.print(debug_show(result8)); + assert(result8 == #ok(42)); + + Debug.print("All candyToNat16 tests passed."); + }; + test("testCandyToNat16", testCandyToNat16); + + func testCandyToNat32() { + // Test case 1: Valid Nat32 input + let result1 = Conversion.candyToNat32(#Nat32(4294967295)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(4294967295)); + + // Test case 2: Valid Nat input within Nat32 range + let result2 = Conversion.candyToNat32(#Nat(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(42)); + + // Test case 3: Nat input exceeding Nat32 range + let result3 = Conversion.candyToNat32(#Nat(5000000000)); + Debug.print(debug_show(result3)); + assert(result3 == #err("overflow while converting Nat to Nat32")); + + // Test case 4: Valid Float input within Nat32 range + let result4 = Conversion.candyToNat32(#Float(42.0)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(42)); + + // Test case 5: Negative Float input + let result5 = Conversion.candyToNat32(#Float(-42.0)); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Invalid type input + let result6 = Conversion.candyToNat32(#Text("invalid")); + Debug.print(debug_show(result6)); + assert(result6 == #err("illegal cast")); + + // Test case 7: Negative Int input + let result7 = Conversion.candyToNat32(#Int(-42)); + Debug.print(debug_show(result7)); + assert(result7 == #err("illegal cast")); + + // Test case 8: Valid Int input within Nat32 range + let result8 = Conversion.candyToNat32(#Int(42)); + Debug.print(debug_show(result8)); + assert(result8 == #ok(42)); + + Debug.print("All candyToNat32 tests passed."); + }; + test("testCandyToNat32", testCandyToNat32); + + func testCandyToNat64() { + // Test case 1: Valid Nat64 input + let result1 = Conversion.candyToNat64(#Nat64(18446744073709551615)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(18446744073709551615)); + + // Test case 2: Valid Nat input within Nat64 range + let result2 = Conversion.candyToNat64(#Nat(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(42)); + + // Test case 3: Valid Float input within Nat64 range + let result3 = Conversion.candyToNat64(#Float(42.0)); + Debug.print(debug_show(result3)); + assert(result3 == #ok(42)); + + // Test case 4: Negative Float input + let result4 = Conversion.candyToNat64(#Float(-42.0)); + Debug.print(debug_show(result4)); + assert(result4 == #err("illegal cast")); + + // Test case 5: Invalid type input + let result5 = Conversion.candyToNat64(#Text("invalid")); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Negative Int input + let result6 = Conversion.candyToNat64(#Int(-42)); + Debug.print(debug_show(result6)); + assert(result6 == #err("illegal cast")); + + // Test case 7: Valid Int input within Nat64 range + let result7 = Conversion.candyToNat64(#Int(42)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(42)); + + Debug.print("All candyToNat64 tests passed."); + }; + test("testCandyToNat64", testCandyToNat64); + + func testCandyToInt() { + // Test case 1: Valid Int input + let result1 = Conversion.candyToInt(#Int(42)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(42)); + + // Test case 2: Valid Int8 input + let result2 = Conversion.candyToInt(#Int8(-128)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(-128)); + + // Test case 3: Valid Int16 input + let result3 = Conversion.candyToInt(#Int16(32767)); + Debug.print(debug_show(result3)); + assert(result3 == #ok(32767)); + + // Test case 4: Valid Int32 input + let result4 = Conversion.candyToInt(#Int32(-2147483648)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(-2147483648)); + + // Test case 5: Valid Int64 input + let result5 = Conversion.candyToInt(#Int64(9223372036854775807)); + Debug.print(debug_show(result5)); + assert(result5 == #ok(9223372036854775807)); + + // Test case 6: Valid Nat input + let result6 = Conversion.candyToInt(#Nat(42)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(42)); + + // Test case 7: Valid Float input + let result7 = Conversion.candyToInt(#Float(42.5)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(42)); + + // Test case 8: Invalid type input + let result8 = Conversion.candyToInt(#Text("invalid")); + Debug.print(debug_show(result8)); + assert(result8 == #err("illegal cast")); + + Debug.print("All candyToInt tests passed."); + }; + test("testCandyToInt", testCandyToInt); + + func testCandyToInt8() { + // Test case 1: Valid Int8 input + let result1 = Conversion.candyToInt8(#Int8(-128)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(-128)); + + // Test case 2: Valid Int input within Int8 range + let result2 = Conversion.candyToInt8(#Int(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(42)); + + // Test case 3: Int input exceeding Int8 range + let result3 = Conversion.candyToInt8(#Int(200)); + Debug.print(debug_show(result3)); + assert(result3 == #err("illegal cast")); + + // Test case 4: Valid Nat8 input + let result4 = Conversion.candyToInt8(#Nat8(127)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(127)); + + // Test case 5: Nat8 input exceeding Int8 range + let result5 = Conversion.candyToInt8(#Nat8(255)); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Valid Float input within Int8 range + let result6 = Conversion.candyToInt8(#Float(42.0)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(42)); + + // Test case 7: Negative Float input + let result7 = Conversion.candyToInt8(#Float(-42.0)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(-42)); + + // Test case 8: Invalid type input + let result8 = Conversion.candyToInt8(#Text("invalid")); + Debug.print(debug_show(result8)); + assert(result8 == #err("illegal cast")); + + Debug.print("All candyToInt8 tests passed."); + }; + test("testCandyToInt8", testCandyToInt8); + + func testCandyToInt16() { + // Test case 1: Valid Int16 input + let result1 = Conversion.candyToInt16(#Int16(32767)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(32767)); + + // Test case 2: Valid Int input within Int16 range + let result2 = Conversion.candyToInt16(#Int(-32768)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(-32768)); + + // Test case 3: Int input exceeding Int16 range + let result3 = Conversion.candyToInt16(#Int(40000)); + Debug.print(debug_show(result3)); + assert(result3 == #err("illegal cast")); + + // Test case 4: Valid Nat16 input + let result4 = Conversion.candyToInt16(#Nat16(32767)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(32767)); + + // Test case 5: Nat16 input exceeding Int16 range + let result5 = Conversion.candyToInt16(#Nat16(65535)); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Valid Float input within Int16 range + let result6 = Conversion.candyToInt16(#Float(42.0)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(42)); + + // Test case 7: Negative Float input + let result7 = Conversion.candyToInt16(#Float(-42.0)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(-42)); + + // Test case 8: Invalid type input + let result8 = Conversion.candyToInt16(#Text("invalid")); + Debug.print(debug_show(result8)); + assert(result8 == #err("illegal cast")); + + Debug.print("All candyToInt16 tests passed."); + }; + test("testCandyToInt16", testCandyToInt16); + + func testCandyToInt32() { + // Test case 1: Valid Int32 input + let result1 = Conversion.candyToInt32(#Int32(2147483647)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(2147483647)); + + // Test case 2: Valid Int input within Int32 range + let result2 = Conversion.candyToInt32(#Int(-2147483648)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(-2147483648)); + + // Test case 3: Int input exceeding Int32 range + let result3 = Conversion.candyToInt32(#Int(3000000000)); + Debug.print(debug_show(result3)); + assert(result3 == #err("overflow while converting Int to Int32")); + + // Test case 4: Valid Nat32 input + let result4 = Conversion.candyToInt32(#Nat32(2147483647)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(2147483647)); + + // Test case 5: Nat32 input exceeding Int32 range + let result5 = Conversion.candyToInt32(#Nat32(4294967295)); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Valid Float input within Int32 range + let result6 = Conversion.candyToInt32(#Float(42.0)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(42)); + + // Test case 7: Negative Float input + let result7 = Conversion.candyToInt32(#Float(-42.0)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(-42)); + + // Test case 8: Invalid type input + let result8 = Conversion.candyToInt32(#Text("invalid")); + Debug.print(debug_show(result8)); + assert(result8 == #err("illegal cast")); + + Debug.print("All candyToInt32 tests passed."); + }; + test("testCandyToInt32", testCandyToInt32); + + func testCandyToInt64() { + // Test case 1: Valid Int64 input + let result1 = Conversion.candyToInt64(#Int64(9223372036854775807)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(9223372036854775807)); + + // Test case 2: Valid Int input within Int64 range + let result2 = Conversion.candyToInt64(#Int(-9223372036854775808)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(-9223372036854775808)); + + // Test case 3: Int input exceeding Int64 range + let result3 = Conversion.candyToInt64(#Int(10000000000000000000)); + Debug.print(debug_show(result3)); + assert(result3 == #err("overflow while converting Int to Int64")); + + // Test case 4: Valid Nat64 input + let result4 = Conversion.candyToInt64(#Nat64(9223372036854775807)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(9223372036854775807)); + + // Test case 5: Nat64 input exceeding Int64 range + let result5 = Conversion.candyToInt64(#Nat64(18446744073709551615)); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Valid Float input within Int64 range + let result6 = Conversion.candyToInt64(#Float(42.0)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(42)); + + // Test case 7: Negative Float input + let result7 = Conversion.candyToInt64(#Float(-42.0)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(-42)); + + // Test case 8: Invalid type input + let result8 = Conversion.candyToInt64(#Text("invalid")); + Debug.print(debug_show(result8)); + assert(result8 == #err("illegal cast")); + + Debug.print("All candyToInt64 tests passed."); + }; + test("testCandyToInt64", testCandyToInt64); + + func testCandyToFloat() { + // Test case 1: Valid Float input + let result1 = Conversion.candyToFloat(#Float(42.5)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(42.5)); + + // Test case 2: Valid Int input + let result2 = Conversion.candyToFloat(#Int(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(42.0)); + + // Test case 3: Valid Int8 input + let result3 = Conversion.candyToFloat(#Int8(-128)); + Debug.print(debug_show(result3)); + assert(result3 == #ok(-128.0)); + + // Test case 4: Valid Int16 input + let result4 = Conversion.candyToFloat(#Int16(32767)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(32767.0)); + + // Test case 5: Valid Int32 input + let result5 = Conversion.candyToFloat(#Int32(-2147483648)); + Debug.print(debug_show(result5)); + assert(result5 == #ok(-2147483648.0)); + + // Test case 6: Valid Int64 input + let result6 = Conversion.candyToFloat(#Int64(9223372036854775807)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(9223372036854775807.0)); + + // Test case 7: Valid Nat input + let result7 = Conversion.candyToFloat(#Nat(42)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(42.0)); + + // Test case 8: Invalid type input + let result8 = Conversion.candyToFloat(#Text("invalid")); + Debug.print(debug_show(result8)); + assert(result8 == #err("illegal cast")); + + Debug.print("All candyToFloat tests passed."); + }; + test("testCandyToFloat", testCandyToFloat); + + func testCandyToPrincipal() { + // Test case 1: Valid Principal input + let principal = Principal.fromText("aaaaa-aa"); + let result1 = Conversion.candyToPrincipal(#Principal(principal)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(principal)); + + // Test case 2: Invalid type input + let result2 = Conversion.candyToPrincipal(#Text("invalid")); + Debug.print(debug_show(result2)); + assert(result2 == #err("invalid principal")); + + Debug.print("All candyToPrincipal tests passed."); + }; + test("testCandyToPrincipal", testCandyToPrincipal); + + func testCandyToBool() { + // Test case 1: Valid Bool input (true) + let result1 = Conversion.candyToBool(#Bool(true)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(true)); + + // Test case 2: Valid Bool input (false) + let result2 = Conversion.candyToBool(#Bool(false)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(false)); + + // Test case 3: Invalid type input + let result3 = Conversion.candyToBool(#Text("invalid")); + Debug.print(debug_show(result3)); + assert(result3 == #err("illegal cast to Bool")); + + Debug.print("All candyToBool tests passed."); + }; + test("testCandyToBool", testCandyToBool); + + func testCandyToBlob() { + // Test case 1: Valid Blob input + let blob = Blob.fromArray([1, 2, 3]); + let result1 = Conversion.candyToBlob(#Blob(blob)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(blob)); + + // Test case 2: Valid Bytes input + let rawBytes : [Nat8] = [1, 2, 3]; + let bytes = StableBuffer.fromArray(rawBytes); + let result2 = Conversion.candyToBlob(#Bytes(bytes)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(Blob.fromArray(rawBytes))); + + // Test case 3: Valid Text input + let text = "hello"; + let result3 = Conversion.candyToBlob(#Text(text)); + Debug.print(debug_show(result3)); + assert(result3 == #ok(Blob.fromArray(Conversion.textToBytes(text)))); + + // Test case 4: Valid Int input + let intVal = 42; + let result4 = Conversion.candyToBlob(#Int(intVal)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(Blob.fromArray(Conversion.intToBytes(intVal)))); + + // Test case 5: Valid Nat input + let natVal = 42; + let result5 = Conversion.candyToBlob(#Nat(natVal)); + Debug.print(debug_show(result5)); + assert(result5 == #ok(Blob.fromArray(Conversion.natToBytes(natVal)))); + + // Test case 6: Valid Principal input + let principal = Principal.fromText("aaaaa-aa"); + let result6 = Conversion.candyToBlob(#Principal(principal)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(Principal.toBlob(principal))); + + // Test case 7: Invalid type input + let result7 = Conversion.candyToBlob(#Array(StableBuffer.fromArray([]))); + Debug.print(debug_show(result7)); + assert(result7 == #err("illegal cast to Blob")); + + Debug.print("All candyToBlob tests passed."); + }; + test("testCandyToBlob", testCandyToBlob); + + func testCandyToValueArray() { + // Test case 1: Valid Array input + let rawArray : [Types.Candy] = [#Nat(1), #Nat(2), #Nat(3)]; + let array = StableBuffer.fromArray([#Nat(1), #Nat(2), #Nat(3)]); + let result1 = Conversion.candyToValueArray(#Array(array)); + Debug.print(debug_show(result1)); + switch (result1) { + case (#ok(innerArray)) { + assert(Array.equal(innerArray, rawArray, Types.eq)); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 2: Empty Array input + let emptyArray = StableBuffer.fromArray([]); + let result2 = Conversion.candyToValueArray(#Array(emptyArray)); + Debug.print(debug_show(result2)); + switch (result2) { + case (#ok(innerArray)) { + assert(Array.equal(innerArray, StableBuffer.toArray(emptyArray), Types.eq)); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + + // Test case 3: Invalid type input + let result3 = Conversion.candyToValueArray(#Text("invalid")); + Debug.print(debug_show(result3)); + switch (result3) { + case (#err(errMsg)) { + assert(errMsg == "illegal cast to [Candy]"); + }; + case _ { + assert(false); + }; + }; + + Debug.print("All candyToValueArray tests passed."); + }; + test("testCandyToValueArray", testCandyToValueArray); + + func testCandyToBytesBuffer() { + // Test case 1: Valid Bytes input + let bytes: [Nat8] = [1, 2, 3]; + let result1 = Conversion.candyToBytesBuffer(#Bytes(StableBuffer.fromArray(bytes))); + //Debug.print(debug_show(result1)); + assert(switch result1 { + case(#ok(buffer)){ buffer.toArray() == bytes}; + case(#err(_)) {false}; + }); + + // Test case 2: Valid Int input + let intVal = 42; + let result2 = Conversion.candyToBytesBuffer(#Int(intVal)); + //Debug.print(debug_show(result2)); + assert(switch result2 { + case (#ok(buffer)) { buffer.toArray() == Conversion.intToBytes(intVal) }; + case (#err(_)) { false }; + }); + + // Test case 3: Valid Nat input + let natVal = 42; + let result3 = Conversion.candyToBytesBuffer(#Nat(natVal)); + //Debug.print(debug_show(result3)); + assert(switch result3 { + case (#ok(buffer)) { buffer.toArray() == Conversion.natToBytes(natVal) }; + case (#err(_)) { false }; + }); + + // Test case 4: Valid Text input + let text = "hello"; + let result4 = Conversion.candyToBytesBuffer(#Text(text)); + //Debug.print(debug_show(result4)); + assert(switch result4 { + case (#ok(buffer)) { buffer.toArray() == Conversion.textToBytes(text) }; + case (#err(_)) { false }; + }); + + // Test case 5: Valid Bool input + let boolVal = true; + let result5 = Conversion.candyToBytesBuffer(#Bool(boolVal)); + //Debug.print(debug_show(result5)); + assert(switch result5 { + case (#ok(buffer)) { buffer.toArray() == Conversion.boolToBytes(boolVal) }; + case (#err(_)) { false }; + }); + + // Test case 6: Valid Blob input + let blob = Blob.fromArray([1, 2, 3]); + let result6 = Conversion.candyToBytesBuffer(#Blob(blob)); + //Debug.print(debug_show(result6)); + assert(switch result6 { + case (#ok(buffer)) { buffer.toArray() == Blob.toArray(blob) }; + case (#err(_)) { false }; + }); + + // Test case 7: Valid Principal input + let principal = Principal.fromText("aaaaa-aa"); + let result7 = Conversion.candyToBytesBuffer(#Principal(principal)); + //Debug.print(debug_show(result7)); + assert(switch result7 { + case (#ok(buffer)) { buffer.toArray() == Conversion.principalToBytes(principal) }; + case (#err(_)) { false }; + }); + + // Test case 8: Invalid type input + let result8 = Conversion.candyToBytesBuffer(#Array(StableBuffer.fromArray([]))); + //Debug.print(debug_show(result8)); + assert(switch result8 { + case (#err(msg)) { msg == "conversion from Array to Bytes not implemented" }; + case (_) { false }; + }); + + Debug.print("All candyToBytesBuffer tests passed."); + }; + test("testCandyToBytesBuffer", testCandyToBytesBuffer); + + func testCandyToMap() { + // Test case 1: Valid Map input + let map = Map.new(); + ignore Map.put(map, Map.thash, "key1", #Nat(42)); + ignore Map.put(map, Map.thash, "key2", #Text("value")); + let result1 = Conversion.candyToMap(#Map(map)); + Debug.print(debug_show(result1)); + switch (result1) { + case (#ok(resMap)) { + + assert(Map.size(resMap) == 2); + switch (Map.get(resMap, Map.thash, "key1")) { + case (?#Nat(42)) {}; + case (_) { assert(false); }; + }; + switch (Map.get(resMap, Map.thash, "key2")) { + case (?#Text("value")) {}; + case (_) { assert(false); }; + }; + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + + // Test case 2: Empty Map input + let emptyMap = Map.new(); + let result2 = Conversion.candyToMap(#Map(emptyMap)); + Debug.print(debug_show(result2)); + switch (result2) { + case (#ok(resMap)) { + assert(Array.equal<(Text, Types.Candy)>(Iter.toArray(Map.entries(resMap)), Iter.toArray(Map.entries(emptyMap)), func ((k1, v1), (k2, v2)) { k1 == k2 and Types.eq(v1,v2) })); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + + // Test case 3: Invalid type input + let result3 = Conversion.candyToMap(#Text("invalid")); + Debug.print(debug_show(result3)); + switch (result3) { + case (#err(errMsg)) { + assert(errMsg == "conversion to Map not supported"); + }; + case (_) { + assert(false); + }; + }; + + Debug.print("All candyToMap tests passed."); + }; + test("testCandyToMap", testCandyToMap); + + func testCandyToBytes() { + // Test case 1: Valid Int input + let intVal = 42; + let result1 = Conversion.candyToBytes(#Int(intVal)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(Conversion.intToBytes(intVal))); + + // Test case 2: Valid Nat input + let natVal = 42; + let result2 = Conversion.candyToBytes(#Nat(natVal)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(Conversion.natToBytes(natVal))); + + // Test case 3: Valid Nat8 input + let nat8Val : Nat8 = 255; + let result3 = Conversion.candyToBytes(#Nat8(nat8Val)); + Debug.print(debug_show(result3)); + assert(result3 == #ok([nat8Val])); + + // Test case 4: Valid Text input + let text = "hello"; + let result4 = Conversion.candyToBytes(#Text(text)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(Conversion.textToBytes(text))); + + // Test case 5: Valid Bool input + let boolVal = true; + let result5 = Conversion.candyToBytes(#Bool(boolVal)); + Debug.print(debug_show(result5)); + assert(result5 == #ok(Conversion.boolToBytes(boolVal))); + + // Test case 6: Valid Blob input + let blob = Blob.fromArray([1, 2, 3]); + let result6 = Conversion.candyToBytes(#Blob(blob)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(Blob.toArray(blob))); + + // Test case 7: Valid Principal input + let principal = Principal.fromText("aaaaa-aa"); + let result7 = Conversion.candyToBytes(#Principal(principal)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(Conversion.principalToBytes(principal))); + + // Test case 8: Invalid type input + let result8 = Conversion.candyToBytes(#Array(StableBuffer.fromArray([]))); + Debug.print(debug_show(result8)); + switch (result8) { + case (#err(errMsg)) { + assert(errMsg == "conversion from Array to Bytes not implemented"); + }; + case _ { + assert(false); + }; + }; + + Debug.print("All candyToBytes tests passed."); + }; + test("testCandyToBytes", testCandyToBytes); + + func testCandyToNatsBuffer() { + // Test case 1: Valid Nats input + let nats : [Nat] = [1,2,3]; + let result1 = Conversion.candyToNatsBuffer(#Nats(StableBuffer.fromArray(nats))); + //Debug.print(debug_show(result1)); + assert(switch result1 { + case (#ok(buffer)) { buffer.toArray() == nats }; + case (#err(_)) { false }; + }); + + // Test case 2: Valid Nat input + let natVal = 42; + let result2 = Conversion.candyToNatsBuffer(#Nat(natVal)); + //Debug.print(debug_show(result2)); + assert(switch result2 { + case (#ok(buffer)) { buffer.toArray() == [natVal] }; + case (#err(_)) { false }; + }); + + // Test case 3: Invalid type input + let result3 = Conversion.candyToNatsBuffer(#Text("invalid")); + //Debug.print(debug_show(result3)); + assert(switch result3 { + case (#err(msg)) { + Debug.print("Error message: " # msg); + msg == "illegal cast" }; + case (_) { false }; + }); + + Debug.print("All candyToNatsBuffer tests passed."); + }; + test("testCandyToNatsBuffer", testCandyToNatsBuffer); + + func testCandyToFloatsBuffer() { + // Test case 1: Valid Floats input + let floats = [1.1, 2.2, 3.3]; + let result1 = Conversion.candyToFloatsBuffer(#Floats(StableBuffer.fromArray(floats))); + //Debug.print(debug_show(result1)); + assert(switch result1 { + case (#ok(buffer)) { buffer.toArray() == floats }; + case (#err(_)) { false }; + }); + + // Test case 2: Valid Float input + let floatVal = 42.5; + let result2 = Conversion.candyToFloatsBuffer(#Float(floatVal)); + //Debug.print(debug_show(result2)); + assert(switch result2 { + case (#ok(buffer)) { buffer.toArray() == [floatVal] }; + case (#err(_)) { false }; + }); + + // Test case 3: Invalid type input + let result3 = Conversion.candyToFloatsBuffer(#Text("invalid")); + //Debug.print(debug_show(result3)); + assert(switch result3 { + case (#err(msg)) { msg == "illegal cast" }; + case (_) { false }; + }); + + Debug.print("All candyToFloatsBuffer tests passed."); + }; + test("testCandyToFloatsBuffer", testCandyToFloatsBuffer); + + func testBytesToInt() { + Debug.print("Testing bytesToInt..." # debug_show(Conversion.intToBytes(0))); + // Test case 1: Convert bytes representing a positive Int + let bytes1: [Nat8] = [0, 42]; + let #ok(result1) = Conversion.bytesToInt(bytes1) else return assert(false); + Debug.print(debug_show(result1)); + assert(result1 == 42); + + // Test case 2: Convert bytes representing a negative Int + let bytes2: [Nat8] = [1, 42]; + let #ok(result2) = Conversion.bytesToInt(bytes2) else return assert(false); + Debug.print(debug_show(result2)); + assert(result2 == -42); + + // Test case 3: Convert bytes representing zero + let bytes3: [Nat8] = [0]; + let #ok(result3) = Conversion.bytesToInt(bytes3) else return assert false; + Debug.print(debug_show(result3)); + assert(result3 == 0); //special case + + // Test case 4: Convert bytes representing a large positive Int + let bytes4: [Nat8] = [0, 1, 0]; + let #ok(result4) = Conversion.bytesToInt(bytes4) else return assert(false); + Debug.print(debug_show(result4)); + assert(result4 == 128); + + // Test case 5: Convert bytes representing a large negative Int + let bytes5: [Nat8] = [1, 1, 0]; + let #ok(result5) = Conversion.bytesToInt(bytes5) else return assert(false); + Debug.print(debug_show(result5)); + assert(result5 == -128); + + // Test case 6: Invalid bytes input (empty array) + let #err(result6) = Conversion.bytesToInt([]) else return assert(false); + Debug.print(debug_show(result6)); + assert(result6 == "Invalid byte array size for conversion to Int"); + + Debug.print("All bytesToInt tests passed."); + }; + test("testBytesToInt", testBytesToInt); + + func testBytesToNat() { + // Test case 1: Convert bytes representing a small Nat and back + let natVal1 = 42; + let bytes1 = Conversion.natToBytes(natVal1); + Debug.print(debug_show(bytes1)); + let result1 = Conversion.bytesToNat(bytes1); + Debug.print(debug_show(result1)); + assert(result1 == natVal1); + + // Test case 2: Convert bytes representing zero and back + let natVal2 = 0; + let bytes2 = Conversion.natToBytes(natVal2); + Debug.print(debug_show(bytes2)); + let result2 = Conversion.bytesToNat(bytes2); + Debug.print(debug_show(result2)); + assert(result2 == natVal2); + + // Test case 3: Convert bytes representing a large Nat and back + let natVal3 = 12345678901234567890; + let bytes3 = Conversion.natToBytes(natVal3); + Debug.print(debug_show(bytes3)); + let result3 = Conversion.bytesToNat(bytes3); + Debug.print(debug_show(result3)); + assert(result3 == natVal3); + + // Test case 4: Invalid bytes input (empty array) + let result4 = Conversion.bytesToNat([]); + Debug.print(debug_show(result4)); + assert(result4 == 0); + + Debug.print("All bytesToNat tests passed."); + }; + test("testBytesToNat", testBytesToNat); + + func testBytesToNat16() { + // Test case 1: Convert bytes representing a small Nat16 and back + let nat16Val1: Nat16 = 42; + let bytes1 = Conversion.nat16ToBytes(nat16Val1); + Debug.print(debug_show(bytes1)); + let result1 = Conversion.bytesToNat16(bytes1); + Debug.print(debug_show(result1)); + assert(result1 == nat16Val1); + + // Test case 2: Convert bytes representing zero and back + let nat16Val2: Nat16 = 0; + let bytes2 = Conversion.nat16ToBytes(nat16Val2); + Debug.print(debug_show(bytes2)); + let result2 = Conversion.bytesToNat16(bytes2); + Debug.print(debug_show(result2)); + assert(result2 == nat16Val2); + + // Test case 3: Convert bytes representing the maximum Nat16 and back + let nat16Val3: Nat16 = 65535; + let bytes3 = Conversion.nat16ToBytes(nat16Val3); + Debug.print(debug_show(bytes3)); + let result3 = Conversion.bytesToNat16(bytes3); + Debug.print(debug_show(result3)); + assert(result3 == nat16Val3); + + // Test case 4: Invalid bytes input (empty array) + let result4 = Conversion.bytesToNat16([]); + Debug.print(debug_show(result4)); + assert(result4 == #ok(0)); + + Debug.print("All bytesToNat16 tests passed."); + }; + test("testBytesToNat16", testBytesToNat16); + + func testBytesToNat64() { + // Test case 1: Convert bytes representing a small Nat64 and back + let nat64Val1: Nat64 = 42; + let bytes1 = Conversion.nat64ToBytes(nat64Val1); + Debug.print(debug_show(bytes1)); + let result1 = Conversion.bytesToNat64(bytes1); + Debug.print(debug_show(result1)); + assert(result1 == nat64Val1); + + // Test case 2: Convert bytes representing zero and back + let nat64Val2: Nat64 = 0; + let bytes2 = Conversion.nat64ToBytes(nat64Val2); + Debug.print(debug_show(bytes2)); + let result2 = Conversion.bytesToNat64(bytes2); + Debug.print(debug_show(result2)); + assert(result2 == nat64Val2); + + // Test case 3: Convert bytes representing the maximum Nat64 and back + let nat64Val3: Nat64 = 18446744073709551615; + let bytes3 = Conversion.nat64ToBytes(nat64Val3); + Debug.print(debug_show(bytes3)); + let result3 = Conversion.bytesToNat64(bytes3); + Debug.print(debug_show(result3)); + assert(result3 == nat64Val3); + + // Test case 4: Invalid bytes input (empty array) + let result4 = Conversion.bytesToNat64([]); + + Debug.print(debug_show(result4)); + assert(result4 == #ok(0)); + + Debug.print("All bytesToNat64 tests passed."); + }; + test("testBytesToNat64", testBytesToNat64); + + + func testBytesToPrincipal() { + // Test case 1: Valid bytes input for Principal "aaaaa-aa" + let bytes: [Nat8] = [1, 1, 1, 1, 1, 1, 1]; + let expectedPrincipal = Principal.fromText("djcse-wqbae-aqcai-bae"); + let result1 = Conversion.bytesToPrincipal(bytes); + Debug.print(debug_show(result1)); + assert(result1 == expectedPrincipal); + + // Test case 2: Valid bytes input for Principal "bbbbb-bb" + let bytes2: [Nat8] = [2, 2, 2, 2, 2, 2, 2]; + + let result2 = Conversion.bytesToPrincipal(bytes2); + + Debug.print(debug_show(result2)); + let expectedPrincipal2 = Principal.fromText("jbhcg-5ycai-baeaq-cai"); + assert(result2 == expectedPrincipal2); + + Debug.print("All bytesToPrincipal tests passed."); + }; + test("testBytesToPrincipal", testBytesToPrincipal); + + func testBytesToText() { + // Test case 1: Valid bytes input representing "hello" + let bytes: [Nat8] = [0, 0, 0, 104, 0, 0, 0, 101, 0, 0, 0, 108, 0, 0, 0, 108, 0, 0, 0, 111]; + let result1 = Conversion.bytesToText(bytes); + Debug.print(debug_show(result1)); + assert(result1 == "hello"); + + // Test case 2: Valid bytes input representing an empty string + let emptyBytes: [Nat8] = []; + let result2 = Conversion.bytesToText(emptyBytes); + Debug.print(debug_show(result2)); + assert(result2 == ""); + + // Test case 3: Valid bytes input with partial characters + let partialBytes: [Nat8] = [0, 0, 0, 65, 0, 0, 0, 66]; + let result3 = Conversion.bytesToText(partialBytes); + Debug.print(debug_show(result3)); + assert(result3 == "AB"); + + Debug.print("All bytesToText tests passed."); + }; + test("testBytesToText", testBytesToText); + + func testCandySharedToBlob() { + // Test case 1: Valid Blob input + let blob = Blob.fromArray([1, 2, 3]); + let result1 = Conversion.candySharedToBlob(#Blob(blob)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(blob)); + + // Test case 2: Valid Bytes input + let bytes: [Nat8] = [1, 2, 3]; + let result2 = Conversion.candySharedToBlob(#Bytes(bytes)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(Blob.fromArray(bytes))); + + // Test case 3: Valid Text input + let text = "hello"; + let result3 = Conversion.candySharedToBlob(#Text(text)); + Debug.print(debug_show(result3)); + assert(result3 == #ok(Blob.fromArray(Conversion.textToBytes(text)))); + + // Test case 4: Valid Int input + let intVal = 42; + let result4 = Conversion.candySharedToBlob(#Int(intVal)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(Blob.fromArray(Conversion.intToBytes(intVal)))); + + // Test case 5: Valid Nat input + let natVal = 42; + let result5 = Conversion.candySharedToBlob(#Nat(natVal)); + Debug.print(debug_show(result5)); + assert(result5 == #ok(Blob.fromArray(Conversion.natToBytes(natVal)))); + + // Test case 6: Valid Principal input + let principal = Principal.fromText("aaaaa-aa"); + let result6 = Conversion.candySharedToBlob(#Principal(principal)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(Principal.toBlob(principal))); + + // Test case 7: Invalid type input + let result7 = Conversion.candySharedToBlob(#Array([])); + Debug.print(debug_show(result7)); + assert(result7 == #err("illegal cast to Blob")); + + Debug.print("All candySharedToBlob tests passed."); + }; + test("testCandySharedToBlob", testCandySharedToBlob); + + func testCandySharedToBool() { + // Test case 1: Valid Bool input (true) + let result1 = Conversion.candySharedToBool(#Bool(true)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(true)); + + // Test case 2: Valid Bool input (false) + let result2 = Conversion.candySharedToBool(#Bool(false)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(false)); + + // Test case 3: Invalid type input + let result3 = Conversion.candySharedToBool(#Text("invalid")); + Debug.print(debug_show(result3)); + assert(result3 == #err("illegal cast to Bool")); + + Debug.print("All candySharedToBool tests passed."); + }; + test("testCandySharedToBool", testCandySharedToBool); + + func testCandySharedToBytesBuffer() { + // Test case 1: Valid Bytes input + let bytes: [Nat8] = [1, 2, 3]; + let result1 = Conversion.candySharedToBytesBuffer(#Bytes(bytes)); + //Debug.print(debug_show(result1)); + switch (result1) { + case (#ok(buffer)) { + assert(buffer.toArray() == bytes); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + + // Test case 2: Valid Int input + let intVal = 42; + let result2 = Conversion.candySharedToBytesBuffer(#Int(intVal)); + //Debug.print(debug_show(result2)); + switch (result2) { + case (#ok(buffer)) { + assert(buffer.toArray() == Conversion.intToBytes(intVal)); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 3: Valid Nat input + let natVal = 42; + let result3 = Conversion.candySharedToBytesBuffer(#Nat(natVal)); + //Debug.print(debug_show(result3)); + switch (result3) { + case (#ok(buffer)) { + assert(buffer.toArray() == Conversion.natToBytes(natVal)); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 4: Valid Text input + let text = "hello"; + let result4 = Conversion.candySharedToBytesBuffer(#Text(text)); + //Debug.print(debug_show(result4)); + switch (result4) { + case (#ok(buffer)) { + assert(buffer.toArray() == Conversion.textToBytes(text)); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 5: Valid Bool input + let boolVal = true; + let result5 = Conversion.candySharedToBytesBuffer(#Bool(boolVal)); + //Debug.print(debug_show(result5)); + switch (result5) { + case (#ok(buffer)) { + assert(buffer.toArray() == Conversion.boolToBytes(boolVal)); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 6: Valid Blob input + let blob = Blob.fromArray([1, 2, 3]); + let result6 = Conversion.candySharedToBytesBuffer(#Blob(blob)); + //Debug.print(debug_show(result6)); + switch (result6) { + case (#ok(buffer)) { + assert(buffer.toArray() == Blob.toArray(blob)); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 7: Valid Principal input + let principal = Principal.fromText("aaaaa-aa"); + let result7 = Conversion.candySharedToBytesBuffer(#Principal(principal)); + //Debug.print(debug_show(result7)); + switch (result7) { + case (#ok(buffer)) { + assert(buffer.toArray() == Conversion.principalToBytes(principal)); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 8: Invalid type input + let result8 = Conversion.candySharedToBytesBuffer(#Array([])); + //Debug.print(debug_show(result8)); + switch (result8) { + case (#err(errMsg)) { + assert(errMsg == "conversion from Array to Bytes not implemented"); + }; + case (_) { + assert(false); + }; + }; + + Debug.print("All candySharedToBytesBuffer tests passed."); + }; + test("testCandySharedToBytesBuffer", testCandySharedToBytesBuffer); + + func testCandySharedToFloat() { + // Test case 1: Valid Float input + let result1 = Conversion.candySharedToFloat(#Float(42.5)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(42.5)); + + // Test case 2: Valid Int input + let result2 = Conversion.candySharedToFloat(#Int(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(42.0)); + + // Test case 3: Valid Int8 input + let result3 = Conversion.candySharedToFloat(#Int8(-128)); + Debug.print(debug_show(result3)); + assert(result3 == #ok(-128.0)); + + // Test case 4: Valid Int16 input + let result4 = Conversion.candySharedToFloat(#Int16(32767)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(32767.0)); + + // Test case 5: Valid Int32 input + let result5 = Conversion.candySharedToFloat(#Int32(-2147483648)); + Debug.print(debug_show(result5)); + assert(result5 == #ok(-2147483648.0)); + + // Test case 6: Valid Int64 input + let result6 = Conversion.candySharedToFloat(#Int64(9223372036854775807)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(9223372036854775807.0)); + + // Test case 7: Valid Nat input + let result7 = Conversion.candySharedToFloat(#Nat(42)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(42.0)); + + // Test case 8: Invalid type input + let result8 = Conversion.candySharedToFloat(#Text("invalid")); + Debug.print(debug_show(result8)); + assert(result8 == #err("illegal cast to Float")); + + Debug.print("All candySharedToFloat tests passed."); + }; + test("testCandySharedToFloat", testCandySharedToFloat); + + func testCandySharedToFloatsBuffer() { + // Test case 1: Valid Floats input + let floats: [Float] = [1.1, 2.2, 3.3]; + let result1 = Conversion.candySharedToFloatsBuffer(#Floats(floats)); + //Debug.print(debug_show(result1)); + switch (result1) { + case (#ok(buffer)) { + assert(buffer.toArray() == floats); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 2: Valid Float input + let floatVal = 42.5; + let result2 = Conversion.candySharedToFloatsBuffer(#Float(floatVal)); + //Debug.print(debug_show(result2)); + switch (result2) { + case (#ok(buffer)) { + assert(buffer.toArray() == [floatVal]); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 3: Invalid type input + let #err(result3) = Conversion.candySharedToFloatsBuffer(#Text("invalid")) else return assert(false); + Debug.print(debug_show(result3)); + + assert(result3 == "illegal cast to Float"); + + + Debug.print("All candySharedToFloatsBuffer tests passed."); + }; + test("testCandySharedToFloatsBuffer", testCandySharedToFloatsBuffer); + + func testCandySharedToInt() { + // Test case 1: Valid Int input + let result1 = Conversion.candySharedToInt(#Int(42)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(42)); + + // Test case 2: Valid Int8 input + let result2 = Conversion.candySharedToInt(#Int8(-128)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(-128)); + + // Test case 3: Valid Int16 input + let result3 = Conversion.candySharedToInt(#Int16(32767)); + Debug.print(debug_show(result3)); + assert(result3 == #ok(32767)); + + // Test case 4: Valid Int32 input + let result4 = Conversion.candySharedToInt(#Int32(-2147483648)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(-2147483648)); + + // Test case 5: Valid Int64 input + let result5 = Conversion.candySharedToInt(#Int64(9223372036854775807)); + Debug.print(debug_show(result5)); + assert(result5 == #ok(9223372036854775807)); + + // Test case 6: Valid Nat input + let result6 = Conversion.candySharedToInt(#Nat(42)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(42)); + + // Test case 7: Valid Float input + let result7 = Conversion.candySharedToInt(#Float(42.5)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(42)); + + // Test case 8: Invalid type input + let result8 = Conversion.candySharedToInt(#Text("invalid")); + Debug.print(debug_show(result8)); + assert(result8 == #err("illegal cast to Int")); + + Debug.print("All candySharedToInt tests passed."); + }; + test("testCandySharedToInt", testCandySharedToInt); + + func testCandySharedToInt8() { + // Test case 1: Valid Int8 input + let result1 = Conversion.candySharedToInt8(#Int8(-128)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(-128)); + + // Test case 2: Valid Int input within Int8 range + let result2 = Conversion.candySharedToInt8(#Int(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(42)); + + // Test case 3: Int input exceeding Int8 range + let result3 = Conversion.candySharedToInt8(#Int(200)); + Debug.print(debug_show(result3)); + assert(result3 == #err("overflow while converting Int to Int8")); + + // Test case 4: Valid Nat8 input + let result4 = Conversion.candySharedToInt8(#Nat8(127)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(127)); + + // Test case 5: Nat8 input exceeding Int8 range + let #err(result5) = Conversion.candySharedToInt8(#Nat8(255)) else return assert(false); + Debug.print(debug_show(result5)); + assert(result5 == "overflow while converting Nat8 to Int8"); + + // Test case 6: Valid Float input within Int8 range + let result6 = Conversion.candySharedToInt8(#Float(42.0)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(42)); + + // Test case 7: Negative Float input + let result7 = Conversion.candySharedToInt8(#Float(-42.0)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(-42)); + + // Test case 8: Invalid type input + let result8 = Conversion.candySharedToInt8(#Text("invalid")); + Debug.print(debug_show(result8)); + assert(result8 == #err("illegal cast to Int8")); + + Debug.print("All candySharedToInt8 tests passed."); + }; + test("testCandySharedToInt8", testCandySharedToInt8); + + func testCandySharedToInt16() { + // Test case 1: Valid Int16 input + let result1 = Conversion.candySharedToInt16(#Int16(32767)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(32767)); + + // Test case 2: Valid Int input within Int16 range + let result2 = Conversion.candySharedToInt16(#Int(-32768)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(-32768)); + + // Test case 3: Int input exceeding Int16 range + let result3 = Conversion.candySharedToInt16(#Int(40000)); + Debug.print(debug_show(result3)); + assert(result3 == #err("overflow while converting Int to Int16")); + + // Test case 4: Valid Nat16 input + let result4 = Conversion.candySharedToInt16(#Nat16(32767)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(32767)); + + // Test case 5: Nat16 input exceeding Int16 range + let result5 = Conversion.candySharedToInt16(#Nat16(65535)); + Debug.print(debug_show(result5)); + assert(result5 == #err("overflow while converting Nat16 to Int16")); + + // Test case 6: Valid Float input within Int16 range + let result6 = Conversion.candySharedToInt16(#Float(42.0)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(42)); + + // Test case 7: Negative Float input + let result7 = Conversion.candySharedToInt16(#Float(-42.0)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(-42)); + + // Test case 8: Invalid type input + let result8 = Conversion.candySharedToInt16(#Text("invalid")); + Debug.print(debug_show(result8)); + assert(result8 == #err("illegal cast to Int16")); + + Debug.print("All candySharedToInt16 tests passed."); + }; + test("testCandySharedToInt16", testCandySharedToInt16); + + func testCandySharedToInt32() { + // Test case 1: Valid Int32 input + let result1 = Conversion.candySharedToInt32(#Int32(2147483647)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(2147483647)); + + // Test case 2: Valid Int input within Int32 range + let result2 = Conversion.candySharedToInt32(#Int(-2147483648)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(-2147483648)); + + // Test case 3: Int input exceeding Int32 range + let result3 = Conversion.candySharedToInt32(#Int(3000000000)); + Debug.print(debug_show(result3)); + assert(result3 == #err("overflow while converting Int to Int32")); + + // Test case 4: Valid Nat32 input + let result4 = Conversion.candySharedToInt32(#Nat32(2147483647)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(2147483647)); + + // Test case 5: Nat32 input exceeding Int32 range + let result5 = Conversion.candySharedToInt32(#Nat32(4294967295)); + Debug.print(debug_show(result5)); + assert(result5 == #err("overflow while converting Nat32 to Int32")); + + // Test case 6: Valid Float input within Int32 range + let result6 = Conversion.candySharedToInt32(#Float(42.0)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(42)); + + // Test case 7: Negative Float input + let result7 = Conversion.candySharedToInt32(#Float(-42.0)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(-42)); + + // Test case 8: Invalid type input + let result8 = Conversion.candySharedToInt32(#Text("invalid")); + Debug.print(debug_show(result8)); + assert(result8 == #err("illegal cast to Int32")); + + Debug.print("All candySharedToInt32 tests passed."); + }; + test("testCandySharedToInt32", testCandySharedToInt32); + + func testCandySharedToInt64() { + // Test case 1: Valid Int64 input + let result1 = Conversion.candySharedToInt64(#Int64(9223372036854775807)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(9223372036854775807)); + + // Test case 2: Valid Int input within Int64 range + let result2 = Conversion.candySharedToInt64(#Int(-9223372036854775808)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(-9223372036854775808)); + + // Test case 3: Int input exceeding Int64 range + let result3 = Conversion.candySharedToInt64(#Int(10000000000000000000)); + Debug.print(debug_show(result3)); + assert(result3 == #err("overflow while converting Int to Int64")); + + // Test case 4: Valid Nat64 input + let result4 = Conversion.candySharedToInt64(#Nat64(9223372036854775807)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(9223372036854775807)); + + // Test case 5: Nat64 input exceeding Int64 range + let result5 = Conversion.candySharedToInt64(#Nat64(18446744073709551615)); + Debug.print(debug_show(result5)); + assert(result5 == #err("overflow while converting Nat64 to Int64")); + + // Test case 6: Valid Float input within Int64 range + let result6 = Conversion.candySharedToInt64(#Float(42.0)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(42)); + + // Test case 7: Negative Float input + let result7 = Conversion.candySharedToInt64(#Float(-42.0)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(-42)); + + // Test case 8: Invalid type input + let result8 = Conversion.candySharedToInt64(#Text("invalid")); + Debug.print(debug_show(result8)); + assert(result8 == #err("illegal cast to Int64")); + + Debug.print("All candySharedToInt64 tests passed."); + }; + test("testCandySharedToInt64", testCandySharedToInt64); + + func testCandySharedToIntsBuffer() { + // Test case 1: Valid Ints input + let ints: [Int] = [1, -2, 3]; + let result1 = Conversion.candySharedToIntsBuffer(#Ints(ints)); + //Debug.print(debug_show(result1)); + switch (result1) { + case (#ok(buffer)) { + assert(buffer.toArray() == ints); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 2: Valid Int input + let intVal = 42; + let result2 = Conversion.candySharedToIntsBuffer(#Int(intVal)); + //Debug.print(debug_show(result2)); + switch (result2) { + case (#ok(buffer)) { + assert(buffer.toArray() == [intVal]); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 3: Invalid type input + let result3 = Conversion.candySharedToIntsBuffer(#Text("invalid")); + //Debug.print(debug_show(result3)); + switch (result3) { + case (#err(errMsg)) { + Debug.print("Expected error: " # errMsg); + assert(errMsg == "illegal cast to Int"); + }; + case (_) { + assert(false); + }; + }; + + Debug.print("All candySharedToIntsBuffer tests passed."); + }; + test("testCandySharedToIntsBuffer", testCandySharedToIntsBuffer); + + func testCandySharedToNat() { + // Test case 1: Valid Nat input + let result1 = Conversion.candySharedToNat(#Nat(42)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(42)); + + // Test case 2: Valid Nat8 input + let result2 = Conversion.candySharedToNat(#Nat8(255)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(255)); + + // Test case 3: Valid Float input + let result3 = Conversion.candySharedToNat(#Float(42.0)); + Debug.print(debug_show(result3)); + assert(result3 == #ok(42)); + + // Test case 4: Negative Float input + let result4 = Conversion.candySharedToNat(#Float(-42.0)); + Debug.print(debug_show(result4)); + assert(result4 == #err("illegal cast")); + + // Test case 5: Invalid type input + let result5 = Conversion.candySharedToNat(#Text("invalid")); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Negative Int input + let result6 = Conversion.candySharedToNat(#Int(-42)); + Debug.print(debug_show(result6)); + assert(result6 == #err("illegal cast")); + + // Test case 7: Valid Int input + let result7 = Conversion.candySharedToNat(#Int(42)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(42)); + + Debug.print("All candySharedToNat tests passed."); + }; + test("testCandySharedToNat", testCandySharedToNat); + + func testCandySharedToNat8() { + // Test case 1: Valid Nat8 input + let result1 = Conversion.candySharedToNat8(#Nat8(255)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(255)); + + // Test case 2: Valid Nat input within Nat8 range + let result2 = Conversion.candySharedToNat8(#Nat(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(42)); + + // Test case 3: Nat input exceeding Nat8 range + let result3 = Conversion.candySharedToNat8(#Nat(300)); + Debug.print(debug_show(result3)); + assert(result3 == #err("overflow while converting Nat to Nat8")); + + // Test case 4: Valid Float input within Nat8 range + let result4 = Conversion.candySharedToNat8(#Float(42.0)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(42)); + + // Test case 5: Negative Float input + let result5 = Conversion.candySharedToNat8(#Float(-42.0)); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Invalid type input + let result6 = Conversion.candySharedToNat8(#Text("invalid")); + Debug.print(debug_show(result6)); + assert(result6 == #err("illegal cast")); + + // Test case 7: Negative Int input + let result7 = Conversion.candySharedToNat8(#Int(-42)); + Debug.print(debug_show(result7)); + assert(result7 == #err("illegal cast")); + + // Test case 8: Valid Int input within Nat8 range + let result8 = Conversion.candySharedToNat8(#Int(42)); + Debug.print(debug_show(result8)); + assert(result8 == #ok(42)); + + Debug.print("All candySharedToNat8 tests passed."); + }; + test("testCandySharedToNat8", testCandySharedToNat8); + + func testCandySharedToNat16() { + // Test case 1: Valid Nat16 input + let result1 = Conversion.candySharedToNat16(#Nat16(65535)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(65535)); + + // Test case 2: Valid Nat input within Nat16 range + let result2 = Conversion.candySharedToNat16(#Nat(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(42)); + + // Test case 3: Nat input exceeding Nat16 range + let result3 = Conversion.candySharedToNat16(#Nat(70000)); + Debug.print(debug_show(result3)); + assert(result3 == #err("overflow while converting Nat to Nat16")); + + // Test case 4: Valid Float input within Nat16 range + let result4 = Conversion.candySharedToNat16(#Float(42.0)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(42)); + + // Test case 5: Negative Float input + let result5 = Conversion.candySharedToNat16(#Float(-42.0)); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Invalid type input + let result6 = Conversion.candySharedToNat16(#Text("invalid")); + Debug.print(debug_show(result6)); + assert(result6 == #err("illegal cast")); + + // Test case 7: Negative Int input + let result7 = Conversion.candySharedToNat16(#Int(-42)); + Debug.print(debug_show(result7)); + assert(result7 == #err("illegal cast")); + + // Test case 8: Valid Int input within Nat16 range + let result8 = Conversion.candySharedToNat16(#Int(42)); + Debug.print(debug_show(result8)); + assert(result8 == #ok(42)); + + Debug.print("All candySharedToNat16 tests passed."); + }; + test("testCandySharedToNat16", testCandySharedToNat16); + + func testCandySharedToNat32() { + // Test case 1: Valid Nat32 input + let result1 = Conversion.candySharedToNat32(#Nat32(4294967295)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(4294967295)); + + // Test case 2: Valid Nat input within Nat32 range + let result2 = Conversion.candySharedToNat32(#Nat(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(42)); + + // Test case 3: Nat input exceeding Nat32 range + let result3 = Conversion.candySharedToNat32(#Nat(5000000000)); + Debug.print(debug_show(result3)); + assert(result3 == #err("overflow while converting Nat to Nat32")); + + // Test case 4: Valid Float input within Nat32 range + let result4 = Conversion.candySharedToNat32(#Float(42.0)); + Debug.print(debug_show(result4)); + assert(result4 == #ok(42)); + + // Test case 5: Negative Float input + let result5 = Conversion.candySharedToNat32(#Float(-42.0)); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Invalid type input + let result6 = Conversion.candySharedToNat32(#Text("invalid")); + Debug.print(debug_show(result6)); + assert(result6 == #err("illegal cast")); + + // Test case 7: Negative Int input + let result7 = Conversion.candySharedToNat32(#Int(-42)); + Debug.print(debug_show(result7)); + assert(result7 == #err("illegal cast")); + + // Test case 8: Valid Int input within Nat32 range + let result8 = Conversion.candySharedToNat32(#Int(42)); + Debug.print(debug_show(result8)); + assert(result8 == #ok(42)); + + Debug.print("All candySharedToNat32 tests passed."); + }; + test("testCandySharedToNat32", testCandySharedToNat32); + + func testCandySharedToNat64() { + // Test case 1: Valid Nat64 input + let result1 = Conversion.candySharedToNat64(#Nat64(18446744073709551615)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(18446744073709551615)); + + // Test case 2: Valid Nat input within Nat64 range + let result2 = Conversion.candySharedToNat64(#Nat(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok(42)); + + // Test case 3: Valid Float input within Nat64 range + let result3 = Conversion.candySharedToNat64(#Float(42.0)); + Debug.print(debug_show(result3)); + assert(result3 == #ok(42)); + + // Test case 4: Negative Float input + let result4 = Conversion.candySharedToNat64(#Float(-42.0)); + Debug.print(debug_show(result4)); + assert(result4 == #err("illegal cast")); + + // Test case 5: Invalid type input + let result5 = Conversion.candySharedToNat64(#Text("invalid")); + Debug.print(debug_show(result5)); + assert(result5 == #err("illegal cast")); + + // Test case 6: Negative Int input + let result6 = Conversion.candySharedToNat64(#Int(-42)); + Debug.print(debug_show(result6)); + assert(result6 == #err("illegal cast")); + + // Test case 7: Valid Int input within Nat64 range + let result7 = Conversion.candySharedToNat64(#Int(42)); + Debug.print(debug_show(result7)); + assert(result7 == #ok(42)); + + Debug.print("All candySharedToNat64 tests passed."); + }; + test("testCandySharedToNat64", testCandySharedToNat64); + + func testCandySharedToNatsBuffer() { + // Test case 1: Valid Nats input + let nats: [Nat] = [1, 2, 3]; + let result1 = Conversion.candySharedToNatsBuffer(#Nats(nats)); + //Debug.print(debug_show(result1)); + switch (result1) { + case (#ok(buffer)) { + assert(buffer.toArray() == nats); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 2: Valid Nat input + let natVal = 42; + let result2 = Conversion.candySharedToNatsBuffer(#Nat(natVal)); + //Debug.print(debug_show(result2)); + switch (result2) { + case (#ok(buffer)) { + assert(buffer.toArray() == [natVal]); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 3: Invalid type input + let result3 = Conversion.candySharedToNatsBuffer(#Text("invalid")); + //Debug.print(debug_show(result3)); + switch (result3) { + case (#err(errMsg)) { + assert(errMsg == "conversion from Text to Buffer not implemented"); + }; + case (_) { + assert(false); + }; + }; + + Debug.print("All candySharedToNatsBuffer tests passed."); + }; + + func testCandySharedToPrincipal() { + // Test case 1: Valid Principal input + let principal = Principal.fromText("aaaaa-aa"); + let result1 = Conversion.candySharedToPrincipal(#Principal(principal)); + Debug.print(debug_show(result1)); + assert(result1 == #ok(principal)); + + // Test case 2: Invalid type input + let result2 = Conversion.candySharedToPrincipal(#Text("invalid")); + Debug.print(debug_show(result2)); + assert(result2 == #err("invalid principal")); + + Debug.print("All candySharedToPrincipal tests passed."); + }; + test("testCandySharedToPrincipal", testCandySharedToPrincipal); + + func testCandySharedToProperties() { + // Test case 1: Valid Class input + let propertyMap = [ { name = "prop1"; value = #Nat(42); immutable = true }, + { name = "prop2"; value = #Text("value"); immutable = false }]; + let result1 = Conversion.candySharedToProperties(#Class(propertyMap)); + Debug.print(debug_show(result1)); + switch (result1) { + case (#ok(resMap)) { + assert(Array.size(resMap) == 2); + if(resMap[0].name == "prop1") { + assert(resMap[0].value == #Nat(42)); + assert(resMap[0].immutable == true); + } else { + assert(resMap[1].value == #Nat(42)); + assert(resMap[1].immutable == true); + }; + if(resMap[0].name == "prop2") { + assert(resMap[0].value == #Text("value")); + assert(resMap[0].immutable == false); + } else { + assert(resMap[1].value == #Text("value")); + assert(resMap[1].immutable == false); + }; + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 2: Empty Class input + let emptyPropertyMap = []; + let result2 = Conversion.candySharedToProperties(#Class([])); + Debug.print(debug_show(result2)); + switch (result2) { + case (#ok(resMap)) { + assert(Array.size(resMap) == 0); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 3: Invalid type input + let result3 = Conversion.candySharedToProperties(#Text("invalid")); + Debug.print(debug_show(result3)); + switch (result3) { + case (#err(errMsg)) { + assert(errMsg == "illegal cast to PropertiesShared"); + }; + case (_) { + assert(false); + }; + }; + + Debug.print("All candySharedToProperties tests passed."); + }; + test("testCandySharedToProperties", testCandySharedToProperties); + + func testCandySharedToText() { + // Test case 1: Valid Text input + let result1 = Conversion.candySharedToText(#Text("hello")); + Debug.print(debug_show(result1)); + assert(result1 == #ok("hello")); + + // Test case 2: Valid Nat input + let result2 = Conversion.candySharedToText(#Nat(42)); + Debug.print(debug_show(result2)); + assert(result2 == #ok("42")); + + // Test case 3: Valid Int input + let result3 = Conversion.candySharedToText(#Int(-42)); + Debug.print(debug_show(result3)); + assert(result3 == #ok("-42")); + + // Test case 4: Valid Bool input + let result4 = Conversion.candySharedToText(#Bool(true)); + Debug.print(debug_show(result4)); + assert(result4 == #ok("true")); + + // Test case 5: Valid Float input + let result5 = Conversion.candySharedToText(#Float(42.5)); + Debug.print(debug_show(result5)); + assert(result5 == #ok("42.5")); + + // Test case 6: Valid Principal input + let principal = Principal.fromText("aaaaa-aa"); + let result6 = Conversion.candySharedToText(#Principal(principal)); + Debug.print(debug_show(result6)); + assert(result6 == #ok(Principal.toText(principal))); + + // Test case 7: Valid Blob input + let blob = Blob.fromArray([1, 2, 3]); + let result7 = Conversion.candySharedToText(#Blob(blob)); + Debug.print(debug_show(result7)); + assert(result7 == #ok("010203")); // Assuming Hex encoding + + // Test case 8: Invalid type input + let result8 = Conversion.candySharedToText(#Array([])); + Debug.print(debug_show(result8)); + assert(result8 == #ok("[]")); + + Debug.print("All candySharedToText tests passed."); + }; + test("testCandySharedToText", testCandySharedToText); + + func testCandySharedToValueArray() { + // Test case 1: Valid Array input + let array: [Types.CandyShared] = [#Nat(1), #Text("value"), #Bool(true)]; + let result1 = Conversion.candySharedToValueArray(#Array(array)); + Debug.print(debug_show(result1)); + switch (result1) { + case (#ok(resArray)) { + assert(resArray == array); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 2: Empty Array input + let emptyArray: [Types.CandyShared] = []; + let result2 = Conversion.candySharedToValueArray(#Array(emptyArray)); + Debug.print(debug_show(result2)); + switch (result2) { + case (#ok(resArray)) { + assert(resArray == emptyArray); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 3: Invalid type input + let result3 = Conversion.candySharedToValueArray(#Text("invalid")); + Debug.print(debug_show(result3)); + switch (result3) { + case (#err(errMsg)) { + assert(errMsg == "illegal cast to [CandyShared]"); + }; + case (_) { + assert(false); + }; + }; + + Debug.print("All candySharedToValueArray tests passed."); + }; + test("testCandySharedToValueArray", testCandySharedToValueArray); + + func testCandySharedToValue() { + // Test case 1: Valid Nat input + let result1 = Conversion.candySharedToValue(#Nat(42)); + Debug.print(debug_show(result1)); + assert(result1 == #Nat(42)); + + // Test case 2: Valid Text input + let result2 = Conversion.candySharedToValue(#Text("hello")); + Debug.print(debug_show(result2)); + assert(result2 == #Text("hello")); + + // Test case 3: Valid Bool input + let result3 = Conversion.candySharedToValue(#Bool(true)); + Debug.print(debug_show(result3)); + assert(result3 == #Blob(Blob.fromArray([1]))); + + // Test case 4: Valid Float input + let result4 = Conversion.candySharedToValue(#Float(42.5)); + Debug.print(debug_show(result4)); + assert(result4 == #Text("42.5")); + + // Test case 5: Valid Principal input + let principal = Principal.fromText("aaaaa-aa"); + let result5 = Conversion.candySharedToValue(#Principal(principal)); + Debug.print(debug_show(result5)); + assert(result5 == #Blob(Principal.toBlob(principal))); + + + + Debug.print("All CandySharedToValue tests passed."); + }; + test("testCandySharedToValue", testCandySharedToValue); + + func testCandyToPropertyMap() { + // Test case 1: Valid Class input + let propertyMap = Map.new(); + ignore Map.put(propertyMap, Map.thash, "prop1", { name = "prop1"; value = #Nat(42); immutable = true }); + ignore Map.put(propertyMap, Map.thash, "prop2", { name = "prop2"; value = #Text("value"); immutable = false }); + let result1 = Conversion.candyToPropertyMap(#Class(propertyMap)); + Debug.print(debug_show(result1)); + switch (result1) { + case (#ok(resMap)) { + assert(Map.size(resMap) == 2); + switch (Map.get(resMap, Map.thash, "prop1")) { + case (?val) { + assert(val.name == "prop1"); + assert(Types.eq(val.value, #Nat(42))); + assert(val.immutable == true); + }; + case (_) { assert(false); }; + }; + switch (Map.get(resMap, Map.thash, "prop2")) { + case (?val) { + assert(val.name == "prop2"); + assert(Types.eq(val.value, #Text("value"))); + assert(val.immutable == false); + }; + case (_) { assert(false); }; + }; + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 2: Empty Class input + let emptyPropertyMap = Map.new(); + let result2 = Conversion.candyToPropertyMap(#Class(emptyPropertyMap)); + Debug.print(debug_show(result2)); + switch (result2) { + case (#ok(resMap)) { + assert(Map.size(resMap) == 0); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 3: Invalid type input + let result3 = Conversion.candyToPropertyMap(#Text("invalid")); + Debug.print(debug_show(result3)); + switch (result3) { + case (#err(errMsg)) { + assert(errMsg == "conversion to Map not supported"); + }; + case (_) { + assert(false); + }; + }; + + Debug.print("All candyToPropertyMap tests passed."); + }; + test("testCandyToPropertyMap", testCandyToPropertyMap); + + func testCandyToSet() { + // Test case 1: Valid Set input + let set = Set.new(); + ignore Set.put(set, Types.candyMapHashTool, #Nat(1)); + ignore Set.put(set, Types.candyMapHashTool, #Text("value")); + let result1 = Conversion.candyToSet(#Set(set)); + Debug.print(debug_show(result1)); + switch (result1) { + case (#ok(resSet)) { + assert(Set.size(resSet) == 2); + assert(Set.contains(resSet, Types.candyMapHashTool, #Nat(1)) == ?true); + assert(Set.contains(resSet, Types.candyMapHashTool, #Text("value"))== ?true); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 2: Empty Set input + let emptySet = Set.new(); + let result2 = Conversion.candyToSet(#Set(emptySet)); + Debug.print(debug_show(result2)); + switch (result2) { + case (#ok(resSet)) { + assert(Set.size(resSet) == 0); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 3: Invalid type input + let result3 = Conversion.candyToSet(#Text("invalid")); + Debug.print(debug_show(result3)); + switch (result3) { + case (#err(errMsg)) { + assert(errMsg == "conversion to Set not supported"); + }; + case (_) { + assert(false); + }; + }; + + Debug.print("All candyToSet tests passed."); + }; + test("testCandyToSet", testCandyToSet); + + func testCandyToValueMap() { + // Test case 1: Valid ValueMap input + let valueMap = Map.new(); + ignore Map.put(valueMap, Types.candyMapHashTool, #Nat(1), #Text("value1")); + ignore Map.put(valueMap, Types.candyMapHashTool, #Nat(2), #Text("value2")); + let result1 = Conversion.candyToValueMap(#ValueMap(valueMap)); + Debug.print(debug_show(result1)); + switch (result1) { + case (#ok(resMap)) { + assert(Map.size(resMap) == 2); + switch (Map.get(resMap, Types.candyMapHashTool, #Nat(1))) { + case (?#Text("value1")) {}; + case (_) { assert(false); }; + }; + switch (Map.get(resMap, Types.candyMapHashTool, #Nat(2))) { + case (?#Text("value2")) {}; + case (_) { assert(false); }; + }; + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 2: Empty ValueMap input + let emptyValueMap = Map.new(); + let result2 = Conversion.candyToValueMap(#ValueMap(emptyValueMap)); + Debug.print(debug_show(result2)); + switch (result2) { + case (#ok(resMap)) { + assert(Map.size(resMap) == 0); + }; + case (#err(errMsg)) { + Debug.print("Unexpected error: " # errMsg); + assert(false); + }; + }; + + // Test case 3: Invalid type input + let result3 = Conversion.candyToValueMap(#Text("invalid")); + Debug.print(debug_show(result3)); + switch (result3) { + case (#err(errMsg)) { + assert(errMsg == "conversion to Map not supported"); + }; + case (_) { + assert(false); + }; + }; + + Debug.print("All candyToValueMap tests passed."); + }; + test("testCandyToValueMap", testCandyToValueMap); + + func testCandyToValue() { + // Test case 1: Valid Nat input + let result1 = Conversion.candyToValue(#Nat(42)); + Debug.print(debug_show(result1)); + assert(result1 == #Nat(42)); + + // Test case 2: Valid Text input + let result2 = Conversion.candyToValue(#Text("hello")); + Debug.print(debug_show(result2)); + assert(result2 == #Text("hello")); + + // Test case 3: Valid Bool input + let result3 = Conversion.candyToValue(#Bool(true)); + Debug.print(debug_show(result3)); + assert(result3 == #Blob(Blob.fromArray([1]))); + + // Test case 4: Valid Float input + let result4 = Conversion.candyToValue(#Float(42.5)); + Debug.print(debug_show(result4)); + assert(result4 == #Text("42.5")); + + // Test case 5: Valid Principal input + let principal = Principal.fromText("aaaaa-aa"); + let result5 = Conversion.candyToValue(#Principal(principal)); + Debug.print(debug_show(result5)); + assert(result5 == #Blob(Principal.toBlob(principal))); + + + + Debug.print("All CandyToValue tests passed."); + }; + test("testCandyToValue", testCandyToValue); + + func testIntToBytes() { + // Test case 1: Convert a positive Int to bytes + let intVal1 = 42; + let result1 = Conversion.intToBytes(intVal1); + Debug.print(debug_show(result1)); + assert(result1 == [0, 42]); + + // Test case 2: Convert a negative Int to bytes + let intVal2 = -42; + let result2 = Conversion.intToBytes(intVal2); + Debug.print(debug_show(result2)); + assert(result2 == [1, 42]); + + // Test case 3: Convert zero to bytes + let intVal3 = 0; + let result3 = Conversion.intToBytes(intVal3); + Debug.print(debug_show(result3)); + assert(result3 == [0,0]); + + // Test case 4: Convert a large positive Int to bytes + let intVal4 = 128; + let result4 = Conversion.intToBytes(intVal4); + Debug.print(debug_show(result4)); + assert(result4 == [0, 1, 0]); + + // Test case 5: Convert a large negative Int to bytes + let intVal5 = -128; + let result5 = Conversion.intToBytes(intVal5); + Debug.print(debug_show(result5)); + assert(result5 == [1, 1, 0]); + + Debug.print("All intToBytes tests passed."); + }; + test("testIntToBytes", testIntToBytes); + + func testNatToBytes() { + // Test case 1: Convert a small Nat to bytes and back + let natVal1 = 42; + let bytes1 = Conversion.natToBytes(natVal1); + Debug.print(debug_show(bytes1)); + let result1 = Conversion.bytesToNat(bytes1); + Debug.print(debug_show(result1)); + assert(result1 == natVal1); + + // Test case 2: Convert zero to bytes and back + let natVal2 = 0; + let bytes2 = Conversion.natToBytes(natVal2); + Debug.print(debug_show(bytes2)); + let result2 = Conversion.bytesToNat(bytes2); + Debug.print(debug_show(result2)); + assert(result2 == natVal2); + + // Test case 3: Convert a large Nat to bytes and back + let natVal3 = 12345678901234567890; + let bytes3 = Conversion.natToBytes(natVal3); + Debug.print(debug_show(bytes3)); + let result3 = Conversion.bytesToNat(bytes3); + Debug.print(debug_show(result3)); + assert(result3 == natVal3); + + Debug.print("All natToBytes tests passed."); + }; + test("testNatToBytes", testNatToBytes); + + + func testNat16ToBytes() { + // Test case 1: Convert a small Nat16 to bytes and back + let nat16Val1: Nat16 = 42; + let bytes1 = Conversion.nat16ToBytes(nat16Val1); + Debug.print(debug_show(bytes1)); + let result1 = Conversion.bytesToNat16(bytes1); + Debug.print(debug_show(result1)); + assert(result1 == nat16Val1); + + // Test case 2: Convert zero to bytes and back + let nat16Val2: Nat16 = 0; + let bytes2 = Conversion.nat16ToBytes(nat16Val2); + Debug.print(debug_show(bytes2)); + let result2 = Conversion.bytesToNat16(bytes2); + Debug.print(debug_show(result2)); + assert(result2 == nat16Val2); + + // Test case 3: Convert the maximum Nat16 to bytes and back + let nat16Val3: Nat16 = 65535; + let bytes3 = Conversion.nat16ToBytes(nat16Val3); + Debug.print(debug_show(bytes3)); + let result3 = Conversion.bytesToNat16(bytes3); + Debug.print(debug_show(result3)); + assert(result3 == nat16Val3); + + Debug.print("All nat16ToBytes tests passed."); + }; + test("testNat16ToBytes", testNat16ToBytes); + + func testNat32ToBytes() { + // Test case 1: Convert a small Nat32 to bytes and back + let nat32Val1: Nat32 = 42; + let bytes1 = Conversion.nat32ToBytes(nat32Val1); + Debug.print(debug_show(bytes1)); + let result1 = Conversion.bytesToNat32(bytes1); + Debug.print(debug_show(result1)); + assert(result1 == nat32Val1); + + // Test case 2: Convert zero to bytes and back + let nat32Val2: Nat32 = 0; + let bytes2 = Conversion.nat32ToBytes(nat32Val2); + Debug.print(debug_show(bytes2)); + let result2 = Conversion.bytesToNat32(bytes2); + Debug.print(debug_show(result2)); + assert(result2 == nat32Val2); + + // Test case 3: Convert a large Nat32 to bytes and back + let nat32Val3: Nat32 = 4294967295; + let bytes3 = Conversion.nat32ToBytes(nat32Val3); + Debug.print(debug_show(bytes3)); + let result3 = Conversion.bytesToNat32(bytes3); + Debug.print(debug_show(result3)); + assert(result3 == nat32Val3); + + Debug.print("All nat32ToBytes tests passed."); + }; + test("testNat32ToBytes", testNat32ToBytes); + + func testNat64ToBytes() { + // Test case 1: Convert a small Nat64 to bytes and back + let nat64Val1: Nat64 = 42; + let bytes1 = Conversion.nat64ToBytes(nat64Val1); + Debug.print(debug_show(bytes1)); + let result1 = Conversion.bytesToNat64(bytes1); + Debug.print(debug_show(result1)); + assert(result1 == nat64Val1); + + // Test case 2: Convert zero to bytes and back + let nat64Val2: Nat64 = 0; + let bytes2 = Conversion.nat64ToBytes(nat64Val2); + Debug.print(debug_show(bytes2)); + let result2 = Conversion.bytesToNat64(bytes2); + Debug.print(debug_show(result2)); + assert(result2 == nat64Val2); + + // Test case 3: Convert a large Nat64 to bytes and back + let nat64Val3: Nat64 = 18446744073709551615; + let bytes3 = Conversion.nat64ToBytes(nat64Val3); + Debug.print(debug_show(bytes3)); + let result3 = Conversion.bytesToNat64(bytes3); + Debug.print(debug_show(result3)); + assert(result3 == nat64Val3); + + Debug.print("All nat64ToBytes tests passed."); + }; + test("testNat64ToBytes", testNat64ToBytes); + + func testPrincipalToBytes() { + // Test case 1: Valid Principal input + let principal = Principal.fromText("aaaaa-aa"); + Debug.print(debug_show(principal)); + let result1 = Conversion.principalToBytes(principal); + Debug.print(debug_show(result1)); + assert(result1 == []); + + // Test case 2: Another valid Principal input + let principal2 = Principal.fromText("jbhcg-5ycai-baeaq-cai"); + let result2 = Conversion.principalToBytes(principal2); + Debug.print(debug_show(result2)); + assert(result2 == [2, 2, 2, 2, 2, 2, 2]); + + Debug.print("All principalToBytes tests passed."); + }; + test("testPrincipalToBytes", testPrincipalToBytes); + + + + func testStableBufferToBuffer() { + // Test case 1: Convert a StableBuffer to Buffer + let stableNatBuffer = StableBuffer.fromArray([1, 2, 3, 4]); + let result1 = Conversion.stableBufferToBuffer(stableNatBuffer); + //Debug.print(debug_show(result1)); + assert(result1.toArray() == StableBuffer.toArray(stableNatBuffer)); + + // Test case 2: Convert an empty StableBuffer to Buffer + let emptyStableNatBuffer = StableBuffer.fromArray([]); + let result2 = Conversion.stableBufferToBuffer(emptyStableNatBuffer); + //Debug.print(debug_show(result2)); + assert(result2.toArray() == StableBuffer.toArray(emptyStableNatBuffer)); + + // Test case 3: Convert a StableBuffer to Buffer + let stableTextBuffer = StableBuffer.fromArray(["hello", "world"]); + let result3 = Conversion.stableBufferToBuffer(stableTextBuffer); + //Debug.print(debug_show(result3)); + assert(result3.toArray() == StableBuffer.toArray(stableTextBuffer)); + + // Test case 4: Convert a StableBuffer to Buffer + let stableBoolBuffer = StableBuffer.fromArray([true, false, true]); + let result4 = Conversion.stableBufferToBuffer(stableBoolBuffer); + //Debug.print(debug_show(result4)); + assert(result4.toArray() == StableBuffer.toArray(stableBoolBuffer)); + + Debug.print("All stableBufferToBuffer tests passed."); + }; + test("testStableBufferToBuffer", testStableBufferToBuffer); + + func testTextToByteBuffer() { + // Test case 1: Convert a valid Text to ByteBuffer and back + let text1 = "hello"; + let buffer1 = Conversion.textToByteBuffer(text1); + //Debug.print(debug_show(buffer1)); + assert(text1 == Conversion.bytesToText(buffer1.toArray())); + + + // Test case 2: Convert an empty Text to ByteBuffer and back + let text2 = ""; + let buffer2 = Conversion.textToByteBuffer(text2); + //Debug.print(debug_show(buffer2)); + + assert(Conversion.bytesToText(buffer2.toArray()) == text2); + + // Test case 3: Convert a Text with special characters to ByteBuffer and back + let text3 = "こんにちは世界"; // "Hello World" in Japanese + let buffer3 = Conversion.textToByteBuffer(text3); + //Debug.print(debug_show(buffer3)); + + assert(Conversion.bytesToText(buffer3.toArray()) == text3); + + Debug.print("All textToByteBuffer tests passed."); + }; + test("testTextToByteBuffer", testTextToByteBuffer); + + func testTextToBytes() { + // Test case 1: Convert a valid Text to bytes and back + let text1 = "hello"; + let bytes1 = Conversion.textToBytes(text1); + Debug.print(debug_show(bytes1)); + let result1 = Conversion.bytesToText(bytes1); + Debug.print(debug_show(result1)); + assert(result1 == text1); + + // Test case 2: Convert an empty Text to bytes and back + let text2 = ""; + let bytes2 = Conversion.textToBytes(text2); + Debug.print(debug_show(bytes2)); + let result2 = Conversion.bytesToText(bytes2); + Debug.print(debug_show(result2)); + assert(result2 == text2); + + // Test case 3: Convert a Text with special characters to bytes and back + let text3 = "こんにちは世界"; // "Hello World" in Japanese + let bytes3 = Conversion.textToBytes(text3); + Debug.print(debug_show(bytes3)); + let result3 = Conversion.bytesToText(bytes3); + Debug.print(debug_show(result3)); + assert(result3 == text3); + + Debug.print("All textToBytes tests passed."); + }; + test("testTextToBytes", testTextToBytes); + + func testTextToNat() { + // Test case 1: Convert a valid Text to Nat and back + let text1 = "12345"; + let nat1Opt = Conversion.textToNat(text1); + assert(nat1Opt != null); // Ensure the conversion succeeded + let nat1 = switch (nat1Opt) { + case (?value) value; + + }; + Debug.print(debug_show(nat1)); + let result1 = Conversion.natToBytes(nat1); + Debug.print(debug_show(result1)); + assert(Conversion.bytesToText(result1) == text1); + + // Test case 2: Convert a Text representing zero to Nat and back + let text2 = "0"; + let nat2Opt = Conversion.textToNat(text2); + Debug.print(debug_show(nat2Opt)); + assert(nat2Opt != null); // Ensure the conversion succeeded + let nat2 = switch (nat2Opt) { + case (?value) value; + + }; + let result2 = Conversion.natToBytes(nat2); + Debug.print(debug_show(result2)); + assert(Conversion.bytesToText(result2) == text2); + + // Test case 3: Invalid Text input (non-numeric) + let text3 = "invalid"; + let result3 = Conversion.textToNat(text3); + + Debug.print(debug_show(result3)); + assert(result3 == null); // Ensure the conversion failed + + Debug.print("All textToNat tests passed."); + }; + + func testToBuffer() { + // Test case 1: Convert an array of Nat to Buffer + let natArray: [Nat] = [1, 2, 3, 4]; + let result1 = Conversion.toBuffer(natArray); + //Debug.print(debug_show(result1)); + assert(result1.toArray() == natArray); + + // Test case 2: Convert an empty array to Buffer + let emptyNatArray: [Nat] = []; + let result2 = Conversion.toBuffer(emptyNatArray); + //Debug.print(debug_show(result2)); + assert(result2.toArray() == emptyNatArray); + + // Test case 3: Convert an array of Text to Buffer + let textArray: [Text] = ["hello", "world"]; + let result3 = Conversion.toBuffer(textArray); + //Debug.print(debug_show(result3)); + assert(result3.toArray() == textArray); + + // Test case 4: Convert an array of Bool to Buffer + let boolArray: [Bool] = [true, false, true]; + let result4 = Conversion.toBuffer(boolArray); + //Debug.print(debug_show(result4)); + assert(result4.toArray() == boolArray); + + Debug.print("All toBuffer tests passed."); + }; + test("testToBuffer", testToBuffer); + + func testUnwrapOptionCandyShared() { + // Test case 1: Valid Some CandyShared input + let result1 = Conversion.unwrapOptionCandyShared(#Option(?#Nat(42))); + Debug.print(debug_show(result1)); + assert(result1 == #ok(#Nat(42))); + + // Test case 2: None input + let result2 = Conversion.unwrapOptionCandyShared(#Option(null)); + Debug.print(debug_show(result2)); + assert(result2 == #err("option is null")); + + // Test case 3: Invalid type input + let result3 = Conversion.unwrapOptionCandyShared(#Text("invalid")); + Debug.print(debug_show(result3)); + assert(switch (result3) { + case (#ok(value)) value == #Text("invalid"); + case _ false; + }); + + Debug.print("All unwrapOptionCandyShared tests passed."); + }; + test("testUnwrapOptionCandyShared", testUnwrapOptionCandyShared); + + func testUnwrapOptionCandy() { + // Test case 1: Valid Some Candy input + let result1 = Conversion.unwrapOptionCandy(#Option(?#Nat(42))); + Debug.print(debug_show(result1)); + let unwrappedResult1 = switch (result1) { + case (#ok(value)) value; + case (#err(_)) {assert(false); #Nat(56);} // This should not happen + }; + + assert(Types.eq(unwrappedResult1, #Nat(42))); + + // Test case 2: None input + let result2 = Conversion.unwrapOptionCandy(#Option(null)); + Debug.print(debug_show(result2)); + assert(switch (result2) { + case (#err(msg)) msg == "option is null"; + case _ false; + }); + + // Test case 3: Invalid type input + let result3 = Conversion.unwrapOptionCandy(#Text("invalid")); + Debug.print(debug_show(result3)); + switch (result3) { + case (#ok(value)) { + switch (value) { + case (#Text(text)) { assert(text == "invalid"); }; + case (_) { assert(false); }; // Fail if the value is not #Text + }; + }; + case (_) { + assert(false); // Fail if the result is not #ok + }; + }; + + Debug.print("All unwrapOptionCandy tests passed."); + }; + + test("testUnwrapOptionCandy", testUnwrapOptionCandy); + + test("test absurd principal", func() { + // Test case 1: Invalid Principal input + let bytes : [Nat8] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87]; + let x = Principal.fromBlob(Blob.fromArray(bytes)); + Debug.print(debug_show(x)); + let result = Conversion.bytesToPrincipal(bytes); + Debug.print(debug_show(result)); + }); \ No newline at end of file