-
Notifications
You must be signed in to change notification settings - Fork 697
feat(byte_array): add ByteSpan::to_byte_array
#8416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(byte_array): add ByteSpan::to_byte_array
#8416
Conversation
orizi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 0 of 2 files reviewed, 4 unresolved discussions (waiting on @TomerStarkware)
corelib/src/byte_array.cairo line 635 at r1 (raw file):
remainder_word: 0, remainder_len: downcast(0).unwrap(), }
Suggestion:
data: [].span(),
first_char_start_offset: 0,
remainder_word: 0,
remainder_len: 0,
}corelib/src/byte_array.cairo line 657 at r1 (raw file):
impl ByteSpanIntoByteArray of Into<ByteSpan, ByteArray> { fn into(mut self: ByteSpan) -> ByteArray { let start_offset = upcast(self.first_char_start_offset);
delay the upcast - as not really needed for comparison.
Code quote:
let start_offset = upcast(self.first_char_start_offset);corelib/src/byte_array.cairo line 659 at r1 (raw file):
let start_offset = upcast(self.first_char_start_offset); // Span is aligned to word boundaries. if start_offset == 0 || self.data.is_empty() {
this sounds possibly wrong - as if you had the bytearray "short" and took the sub "hort" you would have empty data, but this implementation would be wrong.
Code quote:
if start_offset == 0 || self.data.is_empty() {corelib/src/test/byte_array_test.cairo line 555 at r1 (raw file):
fn test_span_into_bytearray() { let empty_ba: ByteArray = ""; assert_eq!(empty_ba.span().into(), empty_ba, "empty round-trip");
remove at most tests - this does not add clarity here.
Suggestion:
assert_eq!(empty_ba.span().into(), empty_ba);87a0aa6 to
d8c0e8b
Compare
3ba3ba2 to
3129ad4
Compare
giladchase
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 0 of 2 files reviewed, 4 unresolved discussions (waiting on @orizi and @TomerStarkware)
corelib/src/byte_array.cairo line 657 at r1 (raw file):
Previously, orizi wrote…
delay the upcast - as not really needed for comparison.
Done.
corelib/src/byte_array.cairo line 659 at r1 (raw file):
Previously, orizi wrote…
this sounds possibly wrong - as if you had the bytearray "short" and took the sub "hort" you would have empty data, but this implementation would be wrong.
I'm testing for this case in the next PR, see test_span_slice_under_31_bytes. It works as is, but the conditional (or the way ByteSpan::slice handles < 31 byte slices) is a bit misleading.
Slices that are < 31 bytes (so are held in pending/remainder word as a felt) split off the start prefix and save the word offset-free.
Meaning, the the structure of "short".span().slice(1,4) would be:
ByteSpan {
data: [],
remainder: "hort"
start_offset: 0
}rather than
ByteSpan {
data: [],
remainder: "short"
start_offset: 1
}Motivation for this is detailed in the slice PR, but the tldr is that the logic is simpler, and slice representation more consistent, if we add an invariant that the remainder word cannot have a start offset, just an end offset.
There is a small overhead for this of course (cost of split_bytes31), but i wanted to optimize for simplicity and consistency for starters.
Added a comment to clarify this.
corelib/src/test/byte_array_test.cairo line 555 at r1 (raw file):
Previously, orizi wrote…
remove at most tests - this does not add clarity here.
Done, tnx for letting me know these aren't required 🙏
corelib/src/byte_array.cairo line 635 at r1 (raw file):
remainder_word: 0, remainder_len: downcast(0).unwrap(), }
🙏 Not sure why i thought this wasn't possible.
3129ad4 to
7b0a77a
Compare
orizi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@orizi reviewed all commit messages.
Reviewable status: 0 of 2 files reviewed, 2 unresolved discussions (waiting on @giladchase and @TomerStarkware)
corelib/src/byte_array.cairo line 659 at r1 (raw file):
Previously, giladchase wrote…
I'm testing for this case in the next PR, see
test_span_slice_under_31_bytes. It works as is, but the conditional (or the wayByteSpan::slicehandles < 31 byte slices) is a bit misleading.Slices that are < 31 bytes (so are held in pending/remainder word as a felt) split off the start prefix and save the word offset-free.
Meaning, the the structure of
"short".span().slice(1,4)would be:ByteSpan { data: [], remainder: "hort" start_offset: 0 }rather than
ByteSpan { data: [], remainder: "short" start_offset: 1 }Motivation for this is detailed in the slice PR, but the tldr is that the logic is simpler, and slice representation more consistent, if we add an invariant that the remainder word cannot have a start offset, just an end offset.
There is a small overhead for this of course (cost of split_bytes31), but i wanted to optimize for simplicity and consistency for starters.Added a comment to clarify this.
i'm not sure it is better than allowing the slice itself to be simplest.
imagine, slice of slice of slice, and evaluation only here - this causes actual slicing of data with work, while when doing the final iteration should have been the only actual pricy action.
d8c0e8b to
4dff15c
Compare
7b0a77a to
055a0e3
Compare
4dff15c to
f22f7b5
Compare
055a0e3 to
558ac51
Compare
giladchase
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 0 of 2 files reviewed, 1 unresolved discussion (waiting on @orizi and @TomerStarkware)
corelib/src/byte_array.cairo line 659 at r1 (raw file):
Previously, orizi wrote…
i'm not sure it is better than allowing the slice itself to be simplest.
imagine, slice of slice of slice, and evaluation only here - this causes actual slicing of data with work, while when doing the final iteration should have been the only actual pricy action.
Done.
Discussed offline: start offset will be applied lazily only in into, end-offset is shifted-right on the spot (otherwise we have to save an extra field on ByteSpan in order to apply it lazily, as discussed offline).
ByteSpan::into and bytes31_sliceByteSpan::into
orizi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@orizi reviewed all commit messages.
Reviewable status: 0 of 2 files reviewed, 1 unresolved discussion (waiting on @TomerStarkware)
corelib/src/byte_array.cairo line 696 at r4 (raw file):
fn into(mut self: ByteSpan) -> ByteArray { let remainder_len = upcast(self.remainder_len); let Some(first_word) = self.data.pop_front() else {
can probably mix the code a bit the the rest as well.
Suggestion:
fn into(mut self: ByteSpan) -> ByteArray {
if self.first_char_start_offset == 0 {
let mut ba = ByteArray {
data: self.data.into(),
pending_word: 0,
pending_word_len: 0,
};
ba.append_word(self.remainder_word, self.remainder_len);
return ba;
}
let remainder_len = upcast(self.remainder_len);
let Some(first_word) = self.data.pop_front() else {
orizi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@orizi reviewed 1 of 2 files at r3, 1 of 1 files at r4.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @giladchase and @TomerStarkware)
orizi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@orizi reviewed 1 of 1 files at r13, all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on @TomerStarkware)
1000d8d to
1379fb9
Compare
b581c8f to
3910f15
Compare
orizi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@orizi reviewed 1 of 1 files at r14, all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on @TomerStarkware)
1379fb9 to
ef06e84
Compare
3910f15 to
c27c17f
Compare
orizi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@orizi reviewed 2 of 2 files at r15, all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on @TomerStarkware)
c27c17f to
ddbba3e
Compare
36fe3fb to
dc2c4f0
Compare
26ed464 to
4903e01
Compare
dc2c4f0 to
a4b8ab5
Compare
4903e01 to
1ec28a3
Compare
a4b8ab5 to
1fb81cc
Compare
orizi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@orizi reviewed 2 of 2 files at r16, all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on @TomerStarkware)
When slicing bytespans (to-be-implemented), the end-offset is trimmed by shifting the word to the right. The left offset, however, will be trimmed lazily only if the `ByteSpan` is casted into a `ByteArray`. Note: Lazily removing the end-offset will require saving an additional field, `end_offset` in `ByteSpan`, due to how strings are represented inside felt252 (the first byte is the msb of the word). In other words, we cannot just reduce the remainder_len, because then it'd be impossible to know how much to trim off from the remainder word at `to_byte_array`.
1fb81cc to
380727c
Compare
1ec28a3 to
2e79d9e
Compare
Merge activity
|

Uh oh!
There was an error while loading. Please reload this page.