user
**GSTrans** string encoding is a method of encoding all 8-bit character values 0-255 with only printable characters. It originates on Acorn computers to allow command line
commands to process non-printable characters.

```
 Character Encoding
 0-31      |letter eg |@, |A, |i |[ etc.
 32-126    character, except for:
 "         |"
 |         ||
 127       |?
 128-255   |! followed by encoding, eg |!|@ = 128

```

A string can be surrounded in quotes, eg "ALERT|G".

See http://www.riscos.com/support/developers/prm/conversions.html

Examples:

```
 |LHello|G|J|M       encodes  CHR$12;"Hello";CHR$7;CHR$10;CHR$13
 "|m|j|@|e|!t|m|!|?" encodes  13,10,0,5,244,13,255

```

Task

:   * Write two functions, one to encode a string of characters into a GSTrans string, and one to decode a GSTrans string. Indicate if any error checking is done, and how it is indicated.
assistant
**Translation of**: Julia

```
# 20231105 Raku programming solution

sub GSTrans-encode(Str $str) {
   return [~] $str.encode('utf8').list.chrs.comb.map: -> $c { 
      my $i = $c.ord;
      die "Char value of $c, $i, is out of range" unless 0 <= $i <= 255;
      given ($i,$c) { 
         when 0 <= $i <= 31    { '|' ~ chr(64 + $i) } 
         when $c eq '"'        { '|"' }
         when $c eq '|'        { '||' }
         when $i == 127        { '|?' }
         when 128 <= $i <= 255 { '|!' ~ GSTrans-encode(chr($i - 128)) }
         default               { $c }
      }
   }
}

sub GSTrans-decode(Str $str) {
   my ($gotbar, $gotbang, $bangadd) = False, False, 0;

   my @result = gather for $str.comb -> $c {
      if $gotbang {
         if $c eq '|' {
            $bangadd = 128;
            $gotbar = True;
         } else {
            take $c.ord + 128;
         }
         $gotbang = False;
      } elsif $gotbar {
         given $c {
            when $c eq '?' { take 127 + $bangadd }
            when $c eq '!' { $gotbang = True }
            when $c eq '|' || $c eq '"' || $c eq '<' { take $c.ord + $bangadd }
            when $c eq '[' || $c eq '{' { take 27 + $bangadd } 
            when $c eq '\\' { take 28 + $bangadd } 
            when $c eq ']' || $c eq '}' { take 29 + $bangadd } 
            when $c eq '^' || $c eq '~' { take 30 + $bangadd }
            when $c eq '_' || $c eq '`' { take 31 + $bangadd }
            default { my $i = $c.uc.ord - 64 + $bangadd;
                      take $i >= 0 ?? $i !! $c.ord      }
         }
         $gotbar = False;
         $bangadd = 0;
      } elsif $c eq '|' {
         $gotbar = True
      } else {
         take $c.ord
      }
   }
   return Blob.new(@result).decode('utf8c8')
}

my @TESTS = <ALERT|G 'wert↑>;
my @RAND_TESTS = ^256 .roll(10).chrs.join xx 8;
my @DECODE_TESTS = < |LHello|G|J|M |m|j|@|e|!t|m|!|? abc|1de|5f >; 

for |@TESTS, |@RAND_TESTS -> $t {
   my $encoded = GSTrans-encode($t);
   my $decoded = GSTrans-decode($encoded);
   say "String $t encoded is: $encoded, decoded is: $decoded.";
   die unless $t ~~ $decoded;
}
for @DECODE_TESTS -> $enc {
    say "Encoded string $enc decoded is: ", GSTrans-decode($enc);
}

```

You may Attempt This Online!