data_streams/lib.rs
1// Copyright 2024 - Strixpyrr
2// SPDX-License-Identifier: Apache-2.0
3
4//! This crate provides stream traits for conveniently read and writing many data types: bytes,
5//! little or big-endian integers, and UTF-8 strings. [`DataSource`] reads from a stream, [`DataSink`]
6//! writes to a stream.
7//!
8//! Implementations for byte slices and `std::io`'s buffered readers and writers are provided, but
9//! it's easy to write your own implementations:
10//!
11//! ```no_run
12//! # use data_streams::{DataSource, DataSink, Result};
13//!
14//! struct MySource {
15//! buffer: Vec<u8>,
16//! // ...
17//! }
18//!
19//! impl DataSource for MySource {
20//! fn available(&self) -> usize {
21//! self.buffer.len()
22//! }
23//!
24//! fn request(&mut self, count: usize) -> Result<bool> {
25//! if self.available() < count {
26//! // Fill the buffer...
27//! }
28//!
29//! Ok(self.available() >= count)
30//! }
31//!
32//! fn skip(&mut self, count: usize) -> Result<usize> {
33//! // Read bytes up to count bytes from the stream...
34//! // Here we just consume from the buffer as an example.
35//! self.buffer.drain(..count);
36//! Ok(count)
37//! }
38//!
39//! fn read_bytes<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a [u8]> {
40//! let count = self.available().min(buf.len());
41//! buf[..count].copy_from_slice(&self.buffer);
42//! self.buffer.drain(..count);
43//! Ok(&buf[..count])
44//! }
45//! }
46//!
47//! struct MySink {
48//! buffer: Vec<u8>,
49//! // ...
50//! }
51//!
52//! impl DataSink for MySink {
53//! fn write_bytes(&mut self, buf: &[u8]) -> Result {
54//! self.buffer.extend_from_slice(buf);
55//! // Flush the buffer?
56//! Ok(())
57//! }
58//! }
59//! ```
60//!
61//! # Feature flags
62//!
63//! - `std`: Provides impls for [`std::io`] types, such as [`BufReader`](std::io::BufReader) and
64//! [`BufWriter`](std::io::BufWriter). Requires a dependency on the Rust standard library. Disable
65//! to allow usage with `no_std`.
66//! - `alloc`: Provides impls for dynamically allocated types such as [`Vec`], and source methods
67//! for reading into these. Requires a heap allocator, which may not be present on platforms
68//! without the standard library.
69//! - `utf8`: Enables reading UTF-8-validated data from sources, and writing to [`String`]s, using a
70//! very fast SIMD validation algorithm from the [`simdutf8`](https://github.com/rusticstuff/simdutf8)
71//! crate. UTF-8 can be written to sinks without this feature.
72//! - `unstable`: Provides unstable features only present on the nightly compiler. Enables:
73//! - `unstable_borrowed_buf`: Provides [`DataSource`] impls for [`BorrowedBuf`](core::io::BorrowedBuf)
74//! and [`BorrowedCursor`](core::io::BorrowedCursor).
75//! - `unstable_specialization`: Enables trait specialization, providing a default [`DataSource`]
76//! for impls of [`BufferAccess`].
77//! - `unstable_uninit_slice`: Provides a [`DataSink`] impl for `&mut [MaybeUninit<u8>]`.
78
79#![cfg_attr(not(feature = "std"), no_std)]
80#![cfg_attr(feature = "unstable_ascii_char", feature(ascii_char))]
81#![cfg_attr(feature = "unstable_specialization", feature(specialization))]
82#![cfg_attr(feature = "unstable_borrowed_buf", feature(core_io_borrowed_buf))]
83#![cfg_attr(feature = "unstable_uninit_slice", feature(maybe_uninit_write_slice))]
84#![cfg_attr(test, feature(assert_matches))]
85#![allow(incomplete_features)]
86
87#![deny(
88 clippy::alloc_instead_of_core,
89 clippy::as_pointer_underscore,
90 clippy::as_underscore,
91 clippy::assertions_on_result_states,
92 clippy::cfg_not_test,
93 clippy::clone_on_ref_ptr,
94 clippy::decimal_literal_representation,
95 clippy::deref_by_slicing,
96 clippy::else_if_without_else,
97 clippy::empty_drop,
98 clippy::empty_enum_variants_with_brackets,
99 clippy::empty_structs_with_brackets,
100 clippy::exhaustive_enums,
101 clippy::field_scoped_visibility_modifiers,
102 clippy::if_then_some_else_none,
103 clippy::impl_trait_in_params,
104 clippy::infinite_loop,
105 clippy::map_err_ignore,
106 clippy::mem_forget,
107 clippy::missing_assert_message,
108 clippy::missing_errors_doc,
109 clippy::missing_panics_doc,
110 clippy::missing_safety_doc,
111 clippy::multiple_unsafe_ops_per_block,
112 clippy::panic,
113 clippy::partial_pub_fields,
114 clippy::redundant_type_annotations,
115 clippy::ref_patterns,
116 clippy::renamed_function_params,
117 clippy::semicolon_inside_block,
118 clippy::std_instead_of_alloc,
119 clippy::std_instead_of_core,
120 clippy::undocumented_unsafe_blocks,
121 clippy::unwrap_used,
122)]
123
124#[cfg(feature = "alloc")]
125extern crate alloc;
126extern crate core;
127
128mod error;
129mod source;
130mod sink;
131mod slice;
132mod vec;
133mod core_io;
134mod std_io;
135mod utf8;
136mod wrappers;
137
138pub mod markers {
139 pub mod source {
140 pub use crate::source::markers::{InfiniteSource, SourceSize};
141 }
142}
143
144pub use error::Error;
145#[cfg(feature = "unstable_ascii_char")]
146pub use error::AsciiError;
147#[cfg(feature = "utf8")]
148pub use error::{Utf8Error, Utf8ErrorKind, SimdUtf8Error};
149pub use sink::{DataSink, GenericDataSink};
150#[cfg(feature = "alloc")]
151pub use sink::VecSink;
152pub use source::{BufferAccess, DataSource, GenericDataSource};
153#[cfg(feature = "alloc")]
154pub use source::VecSource;
155
156pub type Result<T = (), E = Error> = core::result::Result<T, E>;