-
Notifications
You must be signed in to change notification settings - Fork 18
Description
Reporting in case this is a bug, but guessing it's just not possible or could be done in a different way:
import { Contract } from '@algorandfoundation/tealscript';
export class Simple extends Contract {
private int_to_ascii(value: uint64): string {
return extract3('0123456789', value, 1);
}
private itoa(value: uint256): string {
if (value === 0) return '0';
return concat(value / 10 > <uint256>0 ? this.itoa(value / 10) : '', this.int_to_ascii(<uint64>(value % 10)));
}
test(): bytes<256> {
return ('hello : ' + this.itoa(1337 as uint256)) as bytes<256>;
}
}Getting this when I build it:
Error: Bad Request: 139:8: extract s beyond 255: 256
The goal is to have test()bytes<256> return a "clamped" string at 256 bytes.
It's a bit of a convoluted example. For context, I'm messing around with the ARC-72 example and trying to get the URI to include the index/token ID as a suffix. So yes, I'm aware the above example works if bytes<256> is replaced with string. Due to the ARC-72 spec, even if I compute this in arc72_tokenURI I'd still run into this error as it also must return bytes<256>.
As a side-note, would be great if that itoa utility was included out-of-the-box, I believe there's a PyTeal utillity equivalent?
Let me know if I can provide anything else. Thanks!
Update:
This sort of works:
import { Contract } from '@algorandfoundation/tealscript';
type Bytes256 = bytes<256>;
export class Simple extends Contract {
/**
* Map single-digit integer to its string representation.
*/
private digitToASCII(value: uint64): string {
return extract3('0123456789', value, 1);
}
/**
* Convert a number to its human-readable string representation.
*/
private numberToString(value: uint256): string {
if (value === 0) return '0';
const prefix = value / 10 > <uint256>0 ? this.numberToString(value / 10) : '';
const suffix = this.digitToASCII(<uint64>(value % 10));
return concat(prefix, suffix);
}
/**
* Concat string with zero bytes to achieve 256 byte length
*/
private stringToBytes256(value: string): Bytes256 {
return castBytes<Bytes256>(value + bzero(256 - len(value)));
}
test(): bytes<256> {
return this.stringToBytes256(this.numberToString(<uint256>1337));
}
}The downside with this approach is that the output, once decoded, is a string with null-terminators. This is probably fine for most scenarios though, just need to be mindful in JS due to how it handles '\x00' when in a string. Most systems will not render that part.
/** Utility to decode a zero-byte padded bytes[256] to a string */
function decodeBytes256ToString(bytes: Uint8Array): string {
return new TextDecoder().decode(new Uint8Array(bytes.filter((n) => n !== 0)));
}From what I can tell, the core issue is that casting to bytes<256> on a plain string works, e.g.:
'some string' as bytes<256>But casting a string value, like after doing some concatenation, does not work, e.g.:
('hello' + ' ' + 'world') as bytes<256> // errors with "extract l beyond 255: 256"output
With concatenation:
192: test2:
193: proto 0 1
194:
195: // contracts/Simple.algo.ts:38
196: // return ('hello' + ' ' + 'world') as bytes<256>;
197: byte 0x68656c6c6f20776f726c6400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
198: byte 0x
199: dup
200: b==
201: assert
202: extract 0 256
203: retsub
Without:
test2:
proto 0 1
// contracts/Simple.algo.ts:37
// return 'hello world' as bytes<256>;
byte 0x68656c6c6f20776f726c640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 // "hello world"
retsub
Metadata
Metadata
Assignees
Labels
Type
Projects
Status