-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add support for
StdString
for Contracts, Scripts, and Predica…
…tes (#1277) * prep new bytes * add setup * fix test * refactor * adjust * tests * improve tests * aDJUST * refactor * add tests * refactor * adjust * adjust * fix length * correct reference * refactor * twenty eagles lick? * adjust * fix post rename * catch magic revert number * fix mapper * add sway projects * add predicate bytes test * add predicate raw slice tests * add bytes and raw slice sway projects * add bytes test for script * add test for raw slice in script input * add sway files * add basic tests * setup string Struct * add basics * clean * tests * add tests * update exhaustive * add sways for predicates and scripts * add tests for string * update * add to interface test * fix: linting warning * add cs * adjust * convert errors * add struct string * cs * cs * pretty * fix prettier and lint post merge * fix assertions * revise * add additional coverage on input validation * Update packages/fuel-gauge/src/std-lib-string.test.ts Co-authored-by: Dhaiwat <dhaiwatpandya@gmail.com> * Update packages/fuel-gauge/src/std-lib-string.test.ts Co-authored-by: Dhaiwat <dhaiwatpandya@gmail.com> * rename * improve assertions --------- Co-authored-by: Nedim Salkić <nedim.salkic@fuel.sh> Co-authored-by: Dhaiwat <dhaiwatpandya@gmail.com>
- Loading branch information
1 parent
4708765
commit 1e496fe
Showing
16 changed files
with
387 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@fuel-ts/abi-coder": minor | ||
"@fuel-ts/program": minor | ||
--- | ||
|
||
Add StdString dynamic string type |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import type { Uint8ArrayWithDynamicData } from '../utilities'; | ||
|
||
import { StdStringCoder } from './stdString'; | ||
|
||
describe('StdStringCoder', () => { | ||
it('should encode an empty string', () => { | ||
const coder = new StdStringCoder(); | ||
const expected: Uint8ArrayWithDynamicData = new Uint8Array([ | ||
0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
]); | ||
expected.dynamicData = { | ||
0: new Uint8Array([]), | ||
}; | ||
|
||
const actual = coder.encode(''); | ||
expect(actual).toStrictEqual(expected); | ||
}); | ||
|
||
it('should encode [hello world]', () => { | ||
const coder = new StdStringCoder(); | ||
const expected: Uint8ArrayWithDynamicData = new Uint8Array([ | ||
0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 11, | ||
]); | ||
expected.dynamicData = { | ||
0: new Uint8Array([104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0, 0, 0, 0, 0]), | ||
}; | ||
|
||
const actual = coder.encode('hello world'); | ||
expect(actual).toStrictEqual(expected); | ||
}); | ||
|
||
it('should encode [H3llo W0rld]', () => { | ||
const coder = new StdStringCoder(); | ||
const expected: Uint8ArrayWithDynamicData = new Uint8Array([ | ||
0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 11, | ||
]); | ||
expected.dynamicData = { | ||
0: new Uint8Array([72, 51, 108, 108, 111, 32, 87, 48, 114, 108, 100, 0, 0, 0, 0, 0]), | ||
}; | ||
|
||
const actual = coder.encode('H3llo W0rld'); | ||
expect(actual).toStrictEqual(expected); | ||
}); | ||
|
||
it('should encode [abcdefghijklmnopqrstuvwxyz1234567890]', () => { | ||
const coder = new StdStringCoder(); | ||
const expected: Uint8ArrayWithDynamicData = new Uint8Array([ | ||
0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 36, | ||
]); | ||
expected.dynamicData = { | ||
0: new Uint8Array([ | ||
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, | ||
116, 117, 118, 119, 120, 121, 122, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 0, 0, 0, 0, | ||
]), | ||
}; | ||
|
||
const actual = coder.encode('abcdefghijklmnopqrstuvwxyz1234567890'); | ||
expect(actual).toStrictEqual(expected); | ||
}); | ||
|
||
it('should decode a string', () => { | ||
const coder = new StdStringCoder(); | ||
const input = new Uint8Array([ | ||
0, 0, 0, 0, 0, 0, 49, 120, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 72, 101, 108, | ||
108, 111, 32, 87, 111, 114, 108, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
]); | ||
const expected = 'Hello World'; | ||
|
||
const [actual, newOffset] = coder.decode(input, 0); | ||
|
||
expect(actual).toEqual(expected); | ||
expect(newOffset).toEqual(24); | ||
}); | ||
|
||
it('should decode a string [with offset]', () => { | ||
const coder = new StdStringCoder(); | ||
const input = new Uint8Array([ | ||
0, 0, 0, 0, 0, 0, 49, 120, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11, 72, 101, 108, | ||
108, 111, 32, 87, 111, 114, 108, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
]); | ||
const expected = 'Hello World'; | ||
|
||
const [actual, newOffset] = coder.decode(input, 16); | ||
|
||
expect(actual).toEqual(expected); | ||
expect(newOffset).toEqual(40); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { concat } from '@ethersproject/bytes'; | ||
import { toUtf8Bytes, toUtf8String } from '@ethersproject/strings'; | ||
import { bn } from '@fuel-ts/math'; | ||
|
||
import { WORD_SIZE } from '../constants'; | ||
import type { Uint8ArrayWithDynamicData } from '../utilities'; | ||
import { BASE_VECTOR_OFFSET, concatWithDynamicData } from '../utilities'; | ||
|
||
import { Coder } from './abstract-coder'; | ||
import { U64Coder } from './u64'; | ||
|
||
export class StdStringCoder extends Coder<string, string> { | ||
static memorySize = 1; | ||
constructor() { | ||
super('struct', 'struct String', BASE_VECTOR_OFFSET); | ||
} | ||
|
||
encode(value: string): Uint8Array { | ||
const parts: Uint8Array[] = []; | ||
|
||
// pointer (ptr) | ||
const pointer: Uint8ArrayWithDynamicData = new U64Coder().encode(BASE_VECTOR_OFFSET); | ||
|
||
// pointer dynamicData, encode the string vector now and attach to its pointer | ||
const data = this.#getPaddedData(value); | ||
pointer.dynamicData = { | ||
0: concatWithDynamicData([data]), | ||
}; | ||
|
||
parts.push(pointer); | ||
|
||
// capacity (cap) | ||
parts.push(new U64Coder().encode(data.byteLength)); | ||
|
||
// length (len) | ||
parts.push(new U64Coder().encode(value.length)); | ||
|
||
return concatWithDynamicData(parts); | ||
} | ||
|
||
#getPaddedData(value: string): Uint8Array { | ||
const data: Uint8Array[] = [toUtf8Bytes(value)]; | ||
|
||
const paddingLength = (WORD_SIZE - (value.length % WORD_SIZE)) % WORD_SIZE; | ||
if (paddingLength) { | ||
data.push(new Uint8Array(paddingLength)); | ||
} | ||
|
||
return concat(data); | ||
} | ||
|
||
decode(data: Uint8Array, offset: number): [string, number] { | ||
const len = data.slice(16, 24); | ||
const length = bn(new U64Coder().decode(len, 0)[0]).toNumber(); | ||
const byteData = data.slice(BASE_VECTOR_OFFSET, BASE_VECTOR_OFFSET + length); | ||
const value = toUtf8String(byteData); | ||
return [value, offset + BASE_VECTOR_OFFSET]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
packages/fuel-gauge/fixtures/forc-projects/predicate-std-lib-string/Forc.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[project] | ||
authors = ["FuelLabs"] | ||
entry = "main.sw" | ||
license = "Apache-2.0" | ||
name = "predicate-std-lib-string" | ||
|
||
[dependencies] |
30 changes: 30 additions & 0 deletions
30
packages/fuel-gauge/fixtures/forc-projects/predicate-std-lib-string/src/main.sw
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
predicate; | ||
|
||
use std::string::String; | ||
|
||
fn validate_string(arg: String) -> bool { | ||
// to be replaced with a simpler assert_eq once | ||
// https://github.com/FuelLabs/sway/issues/4868 is done | ||
let bytes = arg.as_bytes(); | ||
|
||
let inner = String::from_ascii_str("Hello World"); | ||
let expected_bytes = inner.as_bytes(); | ||
|
||
if expected_bytes.len() != bytes.len() { | ||
return false; | ||
} | ||
|
||
let mut i = 0; | ||
while i < bytes.len() { | ||
if expected_bytes.get(i).unwrap() != bytes.get(i).unwrap() { | ||
return false; | ||
} | ||
i += 1; | ||
} | ||
|
||
true | ||
} | ||
|
||
fn main(_arg_0: u64, _arg_1: u64, arg_2: String) -> bool { | ||
validate_string(arg_2) | ||
} |
7 changes: 7 additions & 0 deletions
7
packages/fuel-gauge/fixtures/forc-projects/script-std-lib-string/Forc.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[project] | ||
authors = ["FuelLabs"] | ||
entry = "main.sw" | ||
license = "Apache-2.0" | ||
name = "script-std-lib-string" | ||
|
||
[dependencies] |
24 changes: 24 additions & 0 deletions
24
packages/fuel-gauge/fixtures/forc-projects/script-std-lib-string/src/main.sw
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
script; | ||
|
||
use std::string::String; | ||
|
||
fn validate_string(arg: String) { | ||
// to be replaced with a simpler assert_eq once | ||
// https://github.com/FuelLabs/sway/issues/4868 is done | ||
let bytes = arg.as_bytes(); | ||
|
||
let inner = String::from_ascii_str("Hello World"); | ||
let expected_bytes = inner.as_bytes(); | ||
|
||
assert_eq(expected_bytes.len(), bytes.len()); | ||
|
||
let mut i = 0; | ||
while i < bytes.len() { | ||
assert(expected_bytes.get(i).unwrap() == bytes.get(i).unwrap()); | ||
i += 1; | ||
} | ||
} | ||
|
||
fn main(arg: String) { | ||
validate_string(arg); | ||
} |
7 changes: 7 additions & 0 deletions
7
packages/fuel-gauge/fixtures/forc-projects/std-lib-string/Forc.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[project] | ||
authors = ["FuelLabs"] | ||
entry = "main.sw" | ||
license = "Apache-2.0" | ||
name = "std-lib-string" | ||
|
||
[dependencies] |
Oops, something went wrong.