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}