Is there any base32 implemented based on Motoko, specifically RFC4648 with no padding?

Is there any base32 implemented based on Motoko, specifically RFC4648 with no padding.

I need to convert [Nat8] to Principal, currently in motoko, only [Nat8] can be encoded into the text form of Principal, and this process requires base32, and then use Principal.fromText. Any better methods?

this is only fromText in Principal, if there is a fromBlob, it will be very nice.

1 Like
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<Nat8>(aChar))));
            };
        };
        return result;
    };

    public func principalToBytes(_principal: Principal.Principal) : [Nat8]{
        return textToBytes(Principal.toText(_principal));
    };

    //todo: this should go to Blob once they add Principal.fromBlob
    public func bytesToPrincipal(_bytes: [Nat8]) : Principal.Principal{
        return Principal.fromText(bytesToText(_bytes));
    };
4 Likes

great job!

Is there any more info about bytesToNat32

Sorry about that:

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])));
    };
1 Like

Thanks very much for your help :motoko_go:

I failed.

I get a Principal: yhy6j-huy54-mkzda-m26hc-yklb3-dzz4l-i2ykq-kr7tx-dhxyf-v2c2g-tae, and it’s slice is:
[152, 239, 24, 172, 140, 12, 215, 142, 44, 41, 97, 216, 243, 158, 45, 26, 194, 160, 168, 254, 119, 25, 239, 130, 215, 66, 209, 166, 2]

the first 4 bytes: [152,239,24,172] get the Nat32 2_565_806_252, and Char.fromNat32(2_565_806_252) will be trapped, as there is no unicode char in 2_565_806_252:

The Replica returned an error: code 5, message: "IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: codepoint out of range"

the problem is that the Principal’s slice to Principal text, need crc32, base32 and ascii code:

Successfully converted on the basis of implementing base32:

dfx canister --no-wallet call tools subaccountToPrincipal '(vec { 29;152;239;24;172;140;12;215;142;44;41;97;216;243;158;45;26;194;160;168;254;119;25;239;130;215;66;209;166;2;0;0})'
(principal "yhy6j-huy54-mkzda-m26hc-yklb3-dzz4l-i2ykq-kr7tx-dhxyf-v2c2g-tae")

dfx canister --no-wallet call tools subaccountToPrincipal '(vec {10;0;0;0;0;0;0;0;2;1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;})'
(principal "ryjl3-tyaaa-aaaaa-aaaba-cai")
2 Likes

Unless there’s something extra going on in there you could also simplify the lowercase conversion like this:
https://forum.dfinity.org/t/motoko-type-text-methods-uppercase-and-lowercase/5938/2?u=ori

Yes, it is effective and will be more concise:

2 Likes