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
//
// Copyright (c) 2022 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>
//
use std::borrow::Cow;

pub mod buffer {
    use std::num::NonZeroUsize;
    pub trait ConstructibleBuffer {
        /// Constructs a split buffer that may accept `slice_capacity` segments without allocating.
        /// It may also accept receiving cached writes for `cache_capacity` bytes before needing to reallocate its cache.
        fn with_capacities(slice_capacity: usize, cache_capacity: usize) -> Self;
    }
    pub trait BoundedBuffer {
        /// Indicates how many bytes can still be written to the buffer before it may reject further writes.
        fn remaining_capacity(&self) -> usize;
    }

    pub trait CopyBuffer {
        /// Copies as much of `bytes` as possible inside its cache, returning the amount actually written.
        /// Will return `None` if the write was refused.
        fn write(&mut self, bytes: &[u8]) -> Option<NonZeroUsize>;
        fn write_byte(&mut self, byte: u8) -> Option<NonZeroUsize> {
            self.write(&[byte])
        }
    }
    pub trait Indexable {
        type Index;
        /// Returns an index-like mark that may be used for future operations at the current buffer-end
        fn get_index(&self) -> Self::Index;
        /// Replaces the data following `from` with the contents of `with`.
        ///
        /// This is an exact size operation, to avoid invalidating other marks that may have been made.
        fn replace(&mut self, from: &Self::Index, with: &[u8]) -> bool;
    }
    pub trait InsertBuffer<T> {
        /// Appends a slice to the buffer without copying its data.
        fn append(&mut self, slice: T) -> Option<NonZeroUsize>;
    }
}

pub mod writer {
    pub trait Writer {
        type Buffer;
    }
    pub trait BacktrackableWriter {
        fn mark(&mut self);
        fn revert(&mut self) -> bool;
    }
    pub trait HasWriter {
        type Writer: Writer;
        /// Returns the most appropriate writer for `self`
        fn writer(self) -> Self::Writer;
    }
}

/// 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
            })),
        }
    }
}

pub mod reader {
    pub trait Reader {
        fn read(&mut self, into: &mut [u8]) -> usize;
        #[must_use = "returns true upon success"]
        fn read_exact(&mut self, into: &mut [u8]) -> bool;
        fn read_byte(&mut self) -> Option<u8> {
            let mut byte = 0;
            (self.read(std::slice::from_mut(&mut byte)) != 0).then_some(byte)
        }
        fn remaining(&self) -> usize;
        fn can_read(&self) -> bool {
            self.remaining() != 0
        }
    }
    pub trait HasReader {
        type Reader: Reader;
        /// Returns the most appropriate reader for `self`
        fn reader(self) -> Self::Reader;
    }
}