mirror of
https://github.com/minio/minio-rs.git
synced 2025-12-06 15:26:51 +08:00
184 lines
5.0 KiB
Rust
184 lines
5.0 KiB
Rust
// MinIO Rust Library for Amazon S3 Compatible Cloud Storage
|
|
// Copyright 2023 MinIO, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
use bytes::{Bytes, BytesMut};
|
|
use std::fmt;
|
|
|
|
/// An aggregated collection of `Bytes` objects.
|
|
#[derive(Debug, Clone)]
|
|
pub struct SegmentedBytes {
|
|
segments: Vec<Vec<Bytes>>,
|
|
total_size: usize,
|
|
}
|
|
|
|
impl Default for SegmentedBytes {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl SegmentedBytes {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
segments: Vec::new(),
|
|
total_size: 0,
|
|
}
|
|
}
|
|
|
|
pub fn len(&self) -> usize {
|
|
self.total_size
|
|
}
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
self.total_size == 0
|
|
}
|
|
|
|
pub fn append(&mut self, bytes: Bytes) {
|
|
self.total_size += bytes.len();
|
|
if let Some(last_segment) = self.segments.last_mut() {
|
|
last_segment.push(bytes);
|
|
} else {
|
|
self.segments.push(vec![bytes]);
|
|
}
|
|
}
|
|
|
|
pub fn iter(&self) -> SegmentedBytesIterator {
|
|
SegmentedBytesIterator {
|
|
sb: self,
|
|
current_segment: 0,
|
|
current_segment_index: 0,
|
|
}
|
|
}
|
|
|
|
/// Copy all the content into a single [Bytes] object.
|
|
///
|
|
/// ⚠️ This function is slow and intended for testing/debugging only.
|
|
/// Do not use in performance-critical code.
|
|
pub fn to_bytes(&self) -> Bytes {
|
|
let mut buf = BytesMut::with_capacity(self.total_size);
|
|
for segment in &self.segments {
|
|
for bytes in segment {
|
|
buf.extend_from_slice(bytes);
|
|
}
|
|
}
|
|
buf.freeze()
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for SegmentedBytes {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match std::str::from_utf8(self.to_bytes().as_ref()) {
|
|
Ok(s) => write!(f, "{s}"),
|
|
Err(_) => Ok(()), // or: write!(f, "<invalid utf8>")
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct SegmentedBytesIntoIterator {
|
|
sb: SegmentedBytes,
|
|
current_segment: usize,
|
|
current_segment_index: usize,
|
|
}
|
|
|
|
impl Iterator for SegmentedBytesIntoIterator {
|
|
type Item = Bytes;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
if self.current_segment >= self.sb.segments.len() {
|
|
return None;
|
|
}
|
|
let segment: &Vec<Self::Item> = &self.sb.segments[self.current_segment];
|
|
if self.current_segment_index >= segment.len() {
|
|
self.current_segment += 1;
|
|
self.current_segment_index = 0;
|
|
return self.next();
|
|
}
|
|
let bytes: Self::Item = segment[self.current_segment_index].clone(); // Note: clone of Bytes does not make a deep copy of byte
|
|
self.current_segment_index += 1;
|
|
Some(bytes)
|
|
}
|
|
}
|
|
|
|
impl IntoIterator for SegmentedBytes {
|
|
type Item = Bytes;
|
|
type IntoIter = SegmentedBytesIntoIterator;
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
SegmentedBytesIntoIterator {
|
|
sb: self,
|
|
current_segment: 0,
|
|
current_segment_index: 0,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct SegmentedBytesIterator<'a> {
|
|
sb: &'a SegmentedBytes,
|
|
current_segment: usize,
|
|
current_segment_index: usize,
|
|
}
|
|
|
|
impl Iterator for SegmentedBytesIterator<'_> {
|
|
type Item = Bytes;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
if self.current_segment >= self.sb.segments.len() {
|
|
return None;
|
|
}
|
|
let segment: &Vec<Self::Item> = &self.sb.segments[self.current_segment];
|
|
if self.current_segment_index >= segment.len() {
|
|
self.current_segment += 1;
|
|
self.current_segment_index = 0;
|
|
return Iterator::next(self);
|
|
}
|
|
let bytes: Self::Item = segment[self.current_segment_index].clone(); // Note: clone of Bytes does not make a deep copy of byte
|
|
self.current_segment_index += 1;
|
|
Some(bytes)
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoIterator for &'a SegmentedBytes {
|
|
type Item = Bytes;
|
|
type IntoIter = SegmentedBytesIterator<'a>;
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
SegmentedBytesIterator {
|
|
sb: self,
|
|
current_segment: 0,
|
|
current_segment_index: 0,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<Bytes> for SegmentedBytes {
|
|
fn from(bytes: Bytes) -> Self {
|
|
let total_size = bytes.len();
|
|
Self {
|
|
segments: vec![vec![bytes]],
|
|
total_size,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<String> for SegmentedBytes {
|
|
fn from(s: String) -> Self {
|
|
let total_size = s.len(); // take number of bytes in the string
|
|
Self {
|
|
segments: vec![vec![Bytes::from(s.into_bytes())]],
|
|
total_size,
|
|
}
|
|
}
|
|
}
|