1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
//
// Copyright (c) 2023 ZettaScale Technology
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
//
// Contributors:
//   ZettaScale Zenoh Team, <zenoh@zettascale.tech>
//

//! ⚠️ WARNING ⚠️
//!
//! This crate is intended for Zenoh's internal use.
//!
//! [Click here for Zenoh's documentation](../zenoh/index.html)
//!
//! Provide different buffer implementations used for serialization and deserialization.
#![no_std]
extern crate alloc;

mod bbuf;
mod slice;
pub mod vec;
mod zbuf;
mod zslice;

use alloc::{borrow::Cow, vec::Vec};
pub use bbuf::*;
pub use zbuf::*;
pub use zslice::*;

pub mod writer {
    use crate::ZSlice;
    use core::num::NonZeroUsize;

    #[derive(Debug, Clone, Copy)]
    pub struct DidntWrite;

    pub trait Writer {
        fn write(&mut self, bytes: &[u8]) -> Result<NonZeroUsize, DidntWrite>;
        fn write_exact(&mut self, bytes: &[u8]) -> Result<(), DidntWrite>;
        fn remaining(&self) -> usize;

        fn write_u8(&mut self, byte: u8) -> Result<(), DidntWrite> {
            self.write_exact(core::slice::from_ref(&byte))
        }
        fn write_zslice(&mut self, slice: &ZSlice) -> Result<(), DidntWrite> {
            self.write_exact(slice.as_slice())
        }
        fn can_write(&self) -> bool {
            self.remaining() != 0
        }
        /// Provides a buffer of exactly `len` uninitialized bytes to `f` to allow in-place writing.
        /// `f` must return the number of bytes it actually wrote.
        fn with_slot<F>(&mut self, len: usize, f: F) -> Result<NonZeroUsize, DidntWrite>
        where
            F: FnOnce(&mut [u8]) -> usize;
    }
    pub trait BacktrackableWriter: Writer {
        type Mark;

        fn mark(&mut self) -> Self::Mark;
        fn rewind(&mut self, mark: Self::Mark) -> bool;
    }

    pub trait HasWriter {
        type Writer: Writer;

        /// Returns the most appropriate writer for `self`
        fn writer(self) -> Self::Writer;
    }
}

pub mod reader {
    use crate::ZSlice;
    use core::num::NonZeroUsize;

    #[derive(Debug, Clone, Copy)]
    pub struct DidntRead;

    pub trait Reader {
        fn read(&mut self, into: &mut [u8]) -> Result<NonZeroUsize, DidntRead>;
        fn read_exact(&mut self, into: &mut [u8]) -> Result<(), DidntRead>;
        fn remaining(&self) -> usize;

        /// Returns an iterator of ZSlices such that the sum of their length is _exactly_ `len`.
        fn read_zslices<F: FnMut(ZSlice)>(
            &mut self,
            len: usize,
            for_each_slice: F,
        ) -> Result<(), DidntRead>;

        /// Reads exactly `len` bytes, returning them as a single ZSlice.
        fn read_zslice(&mut self, len: usize) -> Result<ZSlice, DidntRead>;

        fn read_u8(&mut self) -> Result<u8, DidntRead> {
            let mut byte = 0;
            let read = self.read(core::slice::from_mut(&mut byte))?;
            if read.get() == 1 {
                Ok(byte)
            } else {
                Err(DidntRead)
            }
        }

        fn can_read(&self) -> bool {
            self.remaining() != 0
        }
    }

    pub trait BacktrackableReader: Reader {
        type Mark;

        fn mark(&mut self) -> Self::Mark;
        fn rewind(&mut self, mark: Self::Mark) -> bool;
    }

    #[derive(Debug, Clone, Copy)]
    pub struct DidntSiphon;

    pub trait SiphonableReader: Reader {
        fn siphon<W>(&mut self, writer: W) -> Result<NonZeroUsize, DidntSiphon>
        where
            W: crate::writer::Writer;
    }

    pub trait HasReader {
        type Reader: Reader;

        /// Returns the most appropriate reader for `self`
        fn reader(self) -> Self::Reader;
    }
}

/// A trait for buffers that can be composed of multiple non contiguous slices.
pub trait SplitBuffer<'a> {
    type Slices: Iterator<Item = &'a [u8]> + ExactSizeIterator;

    /// Gets all the slices of this buffer.
    fn slices(&'a self) -> Self::Slices;

    /// Returns `true` if the buffer has a length of 0.
    fn is_empty(&'a self) -> bool {
        self.slices().all(|s| s.is_empty())
    }

    /// Returns the number of bytes in the buffer.
    fn len(&'a self) -> usize {
        self.slices().fold(0, |acc, it| acc + it.len())
    }

    /// Returns all the bytes of this buffer in a conitguous slice.
    /// This may require allocation and copy if the original buffer
    /// is not contiguous.
    fn contiguous(&'a self) -> Cow<'a, [u8]> {
        let mut slices = self.slices();
        match slices.len() {
            0 => Cow::Borrowed(b""),
            1 => Cow::Borrowed(slices.next().unwrap()),
            _ => Cow::Owned(slices.fold(Vec::new(), |mut acc, it| {
                acc.extend(it);
                acc
            })),
        }
    }
}