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

Encoding encoder #746

Merged
merged 26 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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
6 changes: 3 additions & 3 deletions Cargo.lock

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

6 changes: 4 additions & 2 deletions commons/zenoh-buffers/src/zbuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ pub struct ZBuf {

impl ZBuf {
#[must_use]
pub fn empty() -> Self {
Self::default()
pub const fn empty() -> Self {
Self {
slices: SingleOrVec::empty(),
}
}

pub fn clear(&mut self) {
Expand Down
31 changes: 24 additions & 7 deletions commons/zenoh-buffers/src/zslice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,24 +92,41 @@ pub struct ZSlice {
}

impl ZSlice {
#[deprecated(note = "use `new` instead")]
pub fn make(
buf: Arc<dyn ZSliceBuffer>,
start: usize,
end: usize,
) -> Result<ZSlice, Arc<dyn ZSliceBuffer>> {
Self::new(buf, start, end)
}

pub fn new(
buf: Arc<dyn ZSliceBuffer>,
start: usize,
end: usize,
) -> Result<ZSlice, Arc<dyn ZSliceBuffer>> {
if start <= end && end <= buf.as_slice().len() {
Ok(ZSlice {
buf,
start,
end,
#[cfg(feature = "shared-memory")]
kind: ZSliceKind::Raw,
})
// unsafe: this operation is safe because we just checked the slice boundaries
Ok(unsafe { ZSlice::new_unchecked(buf, start, end) })
} else {
Err(buf)
}
}

/// # Safety
/// This function does not verify wether the `start` and `end` indexes are within the buffer boundaries.
/// If a [`ZSlice`] is built via this constructor, a later access may panic if `start` and `end` indexes are out-of-bound.
pub unsafe fn new_unchecked(buf: Arc<dyn ZSliceBuffer>, start: usize, end: usize) -> Self {
ZSlice {
buf,
start,
end,
#[cfg(feature = "shared-memory")]
kind: ZSliceKind::Raw,
}
}

#[inline]
#[must_use]
pub fn downcast_ref<T>(&self) -> Option<&T>
Expand Down
2 changes: 1 addition & 1 deletion commons/zenoh-codec/benches/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ fn criterion_benchmark(c: &mut Criterion) {
let mut idx = 0;
while idx < zslice.len() {
let len = (zslice.len() - idx).min(chunk);
zbuf.push_zslice(ZSlice::make(buff.clone(), idx, idx + len).unwrap());
zbuf.push_zslice(ZSlice::new(buff.clone(), idx, idx + len).unwrap());
idx += len;
}

Expand Down
49 changes: 40 additions & 9 deletions commons/zenoh-codec/src/core/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,19 @@ use zenoh_buffers::{
reader::{DidntRead, Reader},
writer::{DidntWrite, Writer},
};
use zenoh_protocol::core::{Encoding, EncodingPrefix};
use zenoh_protocol::{
common::imsg,
core::encoding::{flag, Encoding, EncodingPrefix},
};

impl LCodec<&Encoding> for Zenoh080 {
fn w_len(self, x: &Encoding) -> usize {
1 + self.w_len(x.suffix())
let (prefix, suffix) = (x.prefix(), x.suffix());
let mut len = self.w_len((prefix as u32) << 1);
if !suffix.is_empty() {
len += self.w_len(x.suffix());
}
len
}
}

Expand All @@ -32,9 +40,18 @@ where
type Output = Result<(), DidntWrite>;

fn write(self, writer: &mut W, x: &Encoding) -> Self::Output {
let zodec = Zenoh080Bounded::<EncodingPrefix>::new();
zodec.write(&mut *writer, x.prefix())?;
zodec.write(&mut *writer, x.suffix())?;
let mut prefix = (x.prefix() as u32) << 1;
let suffix = x.suffix();

if !suffix.is_empty() {
prefix |= flag::S;
}
let zodec = Zenoh080Bounded::<u32>::new();
zodec.write(&mut *writer, prefix)?;
if !suffix.is_empty() {
let zodec = Zenoh080Bounded::<u8>::new();
zodec.write(&mut *writer, suffix)?;
}
Ok(())
}
}
Expand All @@ -46,10 +63,24 @@ where
type Error = DidntRead;

fn read(self, reader: &mut R) -> Result<Encoding, Self::Error> {
let zodec = Zenoh080Bounded::<EncodingPrefix>::new();
let prefix: EncodingPrefix = zodec.read(&mut *reader)?;
let suffix: String = zodec.read(&mut *reader)?;
let encoding = Encoding::new(prefix, suffix).map_err(|_| DidntRead)?;
let zodec = Zenoh080Bounded::<u32>::new();
let prefix: u32 = zodec.read(&mut *reader)?;
let (prefix, has_suffix) = (
(prefix >> 1) as EncodingPrefix,
imsg::has_flag(prefix as u8, flag::S as u8),
);

let mut suffix = String::new();
if has_suffix {
let zodec = Zenoh080Bounded::<u8>::new();
suffix = zodec.read(&mut *reader)?;
}

let mut encoding: Encoding = Encoding::new(prefix);
if !suffix.is_empty() {
encoding = encoding.with_suffix(suffix).map_err(|_| DidntRead)?;
}

Ok(encoding)
}
}
10 changes: 9 additions & 1 deletion commons/zenoh-collections/src/single_or_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ enum SingleOrVecInner<T> {
}

impl<T> SingleOrVecInner<T> {
const fn empty() -> Self {
SingleOrVecInner::Vec(Vec::new())
}

fn push(&mut self, value: T) {
match self {
SingleOrVecInner::Vec(vec) if vec.capacity() == 0 => *self = Self::Single(value),
Expand All @@ -50,7 +54,7 @@ where

impl<T> Default for SingleOrVecInner<T> {
fn default() -> Self {
SingleOrVecInner::Vec(Vec::new())
Self::empty()
}
}

Expand Down Expand Up @@ -85,6 +89,10 @@ where
pub struct SingleOrVec<T>(SingleOrVecInner<T>);

impl<T> SingleOrVec<T> {
pub const fn empty() -> Self {
Self(SingleOrVecInner::empty())
}

pub fn push(&mut self, value: T) {
self.0.push(value);
}
Expand Down
1 change: 0 additions & 1 deletion commons/zenoh-protocol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ complete_n = []
const_format = { workspace = true }
hex = { workspace = true, features = ["alloc"] }
rand = { workspace = true, features = ["alloc", "getrandom"], optional = true }
phf = { workspace = true }
serde = { workspace = true, features = ["alloc"] }
uhlc = { workspace = true, default-features = false }
uuid = { workspace = true } # Needs a getrandom::getrandom() custom implementation on embedded (in root crate)
Expand Down
Loading
Loading