praborrow_logistics/
lib.rs

1//! Zero-copy buffer abstraction for raw byte streams.
2//!
3//! Provides `RawResource` for managing raw byte buffers without allocation overhead.
4//! Uses `ManuallyDrop` to take ownership of data while exposing raw pointers.
5//!
6//! # Safety
7//!
8//! This module uses unsafe code to manage memory manually. The `RawResource` struct
9//! takes ownership of a `Vec<u8>` via `ManuallyDrop`, preventing automatic deallocation.
10//! The `Drop` implementation properly reconstructs the `Vec` to ensure memory is freed.
11//!
12//! Caller is responsible for ensuring the buffer outlives all references to it.
13
14#![no_std]
15
16extern crate alloc;
17
18use alloc::vec::Vec;
19use bytes::Bytes;
20
21/// A zero-copy buffer resource representing "Hilirisasi Data" (Downstreaming Data).
22///
23/// This struct wraps `bytes::Bytes` to provide efficient, reference-counted
24/// access to contiguous memory without unnecessary copying.
25#[doc(alias = "PinnedBuffer")]
26#[derive(Clone, Debug, PartialEq, Eq)]
27pub struct RawResource {
28    inner: Bytes,
29}
30
31// Bytes is Send + Sync
32unsafe impl Send for RawResource {}
33unsafe impl Sync for RawResource {}
34
35impl RawResource {
36    /// HILIRISASI DATA: Refines raw data into a downstreamable resource.
37    ///
38    /// Consumes a `Vec<u8>` into a `Bytes` object (zero-copy if possible).
39    ///
40    /// # Errors
41    ///
42    /// Returns an error if the input data is empty.
43    pub fn refine(data: Vec<u8>) -> Result<Self, &'static str> {
44        if data.is_empty() {
45            return Err("Cannot refine empty data: buffer must contain at least one byte");
46        }
47
48        Ok(Self {
49            inner: Bytes::from(data),
50        })
51    }
52
53    /// Returns the raw pointer to the resource data.
54    #[inline]
55    pub fn as_ptr(&self) -> *const u8 {
56        self.inner.as_ptr()
57    }
58
59    /// Returns the length of the resource data in bytes.
60    #[inline]
61    pub fn len(&self) -> usize {
62        self.inner.len()
63    }
64
65    /// Returns `true` if the resource has zero length.
66    #[inline]
67    pub fn is_empty(&self) -> bool {
68        self.inner.is_empty()
69    }
70
71    /// Returns a byte slice of the resource.
72    ///
73    /// # Safety
74    ///
75    /// This method is safe. The `unsafe` keyword is kept for backward compatibility
76    /// but the implementation delegates to safe `Bytes::as_ref()`.
77    ///
78    /// # Safe Usage
79    /// The returned slice is tied to the lifetime of `self`.
80    pub unsafe fn as_slice(&self) -> &[u8] {
81        &self.inner
82    }
83    
84    /// Returns a safe slice.
85    pub fn as_bytes(&self) -> &[u8] {
86        &self.inner
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn test_refine_success() {
96        let data = alloc::vec![1, 2, 3, 4, 5];
97        let resource = RawResource::refine(data).expect("should succeed");
98        assert_eq!(resource.len(), 5);
99        assert!(!resource.is_empty());
100    }
101
102    #[test]
103    fn test_refine_empty_fails() {
104        let data: Vec<u8> = alloc::vec![];
105        let result = RawResource::refine(data);
106        assert!(result.is_err());
107    }
108
109    #[test]
110    fn test_as_slice() {
111        let data = alloc::vec![10, 20, 30];
112        let resource = RawResource::refine(data).expect("should succeed");
113        let slice = unsafe { resource.as_slice() };
114        assert_eq!(slice, &[10, 20, 30]);
115    }
116
117    #[test]
118    fn test_drop_is_called() {
119        // This test verifies Drop doesn't panic. In a real scenario,
120        // you'd use a custom allocator to verify deallocation.
121        let data = alloc::vec![1, 2, 3, 4, 5];
122        let resource = RawResource::refine(data).expect("should succeed");
123        drop(resource);
124        // If we get here without panic/leak detector complaints, Drop works
125    }
126}