Skip to content
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: add bytes_vec features #86

Merged
merged 1 commit into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions bindings/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ faster-hex = { version = "^0.6", optional = true }
[features]
default = ["std"]
std = ["bytes/std", "faster-hex"]
# Provide impls for bytes in no_std environment without depending on atomic
bytes_vec = []

[badges]
maintenance = { status = "experimental" }
55 changes: 55 additions & 0 deletions bindings/rust/src/bytes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use alloc::{borrow::ToOwned, vec::Vec};
use core::{
convert::From,
ops::{Bound, Deref, RangeBounds},
};

#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct Bytes(Vec<u8>);

impl From<Vec<u8>> for Bytes {
fn from(value: Vec<u8>) -> Self {
Self(value)
}
}

impl From<&[u8]> for Bytes {
fn from(value: &[u8]) -> Self {
Self(value.to_owned())
}
}

impl From<Bytes> for Vec<u8> {
fn from(value: Bytes) -> Self {
value.0
}
}

impl Deref for Bytes {
type Target = [u8];

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl Bytes {
pub fn from_static(bytes: &[u8]) -> Self {
Self::from(bytes)
}

pub fn slice(&self, range: impl RangeBounds<usize>) -> Self {
let len = self.len();
let begin = match range.start_bound() {
Bound::Included(&n) => n,
Bound::Excluded(&n) => n + 1,
Bound::Unbounded => 0,
};
let end = match range.end_bound() {
Bound::Included(&n) => n + 1,
Copy link
Collaborator

@eval-exec eval-exec Jan 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be n

use std::ops::Bound::*;
use std::ops::RangeBounds;
fn main() {
    assert_eq!((1..=12).end_bound(), Included(&12));
    assert_eq!((1..13).end_bound(), Excluded(&13));
}
$ cargo run
...
$ echo $?
0

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file is just reverted from #75 , I didn't look into the detail, @yangby-cryptape could you help to check?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the current code is mostly correct. But there's an edge case, when n is usize::MAX. It might be better to pass the range to self.0[..].index directly.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I misunderstood. It's correct.

use std::ops::Bound;
use std::ops::RangeBounds;
fn main() {
    let a = vec![0, 1, 2, 3, 4, 5];

    let exclude_2 = slice(a.clone(), 0..2);
    let include_2 = slice(a.clone(), 0..=2);

    let exclude_5 = slice(a.clone(), 0..5);
    let include_5 = slice(a.clone(), 0..=5);

    dbg!(&exclude_2);
    dbg!(&include_2);

    dbg!(&exclude_5);
    dbg!(&include_5);
}

pub fn slice(src: Vec<u8>, range: impl RangeBounds<usize>) ->Vec<u8> {
    let len = src.len();
    let begin = match range.start_bound() {
        Bound::Included(&n) => n,
        Bound::Excluded(&n) => n + 1,
        Bound::Unbounded => 0,
    };
    let end = match range.end_bound() {
        Bound::Included(&n) => n + 1,
        Bound::Excluded(&n) => n,
        Bound::Unbounded => len,
    };
    src[begin..end].to_vec()
}
 cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/rust-playground`
[src/main.rs:21] &exclude_2 = [
    0,
    1,
]
[src/main.rs:22] &include_2 = [
    0,
    1,
    2,
]
[src/main.rs:24] &exclude_5 = [
    0,
    1,
    2,
    3,
    4,
]
[src/main.rs:25] &include_5 = [
    0,
    1,
    2,
    3,
    4,
    5,
]

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use SliceIndex for (Bound, Bound)

let range = (range.start_bound.cloned(), range.end_bound().cloned());
self.0.index(range)

Copy link
Collaborator

@eval-exec eval-exec Jan 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use SliceIndex for (Bound, Bound)

let range = (range.start_bound.cloned(), range.end_bound().cloned());
self.0.index(range)

But the SliceIndex trait is unsafe.

pub unsafe trait SliceIndex<T: ?Sized>: Sealed {

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's safe to use. It the same as self.0[range]. (Actually, self.0[range] is better.)

Bound::Excluded(&n) => n,
eval-exec marked this conversation as resolved.
Show resolved Hide resolved
Bound::Unbounded => len,
};
Self::from(&self.0[begin..end])
}
}
6 changes: 5 additions & 1 deletion bindings/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ cfg_if::cfg_if! {
if #[cfg(feature = "std")] {
extern crate std;

pub use bytes;
pub mod io {
pub use std::io::{Error, Result, Write};
}
} else {
#[cfg(feature = "bytes_vec")]
pub mod bytes;
#[cfg(not(feature = "bytes_vec"))]
pub use bytes;
pub mod io;
}
}

pub use bytes;
pub mod error;
pub mod prelude;
mod primitive;
Expand Down
4 changes: 2 additions & 2 deletions tools/compiler/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.