33
44use core:: any:: Any ;
55use core:: cell:: Cell ;
6+ use core:: ffi:: CStr ;
67use core:: marker:: PhantomData ;
78
89/// A zero-cost wrapper guaranteed not to share its memory location with any other valid (in-scope)
@@ -71,41 +72,53 @@ impl<T: Any + Send + Sync> NonDeDuplicated<T> {
7172 }
7273}
7374
75+ /// Separate from [bytes_to_array], so that we help monomorphization surface area to be smaller.
76+ const fn copy_bytes_to_array ( to : & mut [ u8 ] , from : & [ u8 ] , len : usize ) {
77+ if from. len ( ) > len {
78+ let msg = match from. len ( ) - len {
79+ 1 => "Target length is 1 byte too small." ,
80+ 2 => "Target length is 2 bytes too small." ,
81+ 3 => "Target length is 3 bytes too small." ,
82+ 4 => "Target length is 4 bytes too small." ,
83+ _ => "Target length is more than 4 bytes too small." ,
84+ } ;
85+ panic ! ( "{}" , msg)
86+ }
87+ if from. len ( ) < len {
88+ let msg = match len - from. len ( ) {
89+ 1 => "Target length is 1 byte too large." ,
90+ 2 => "Target length is 2 bytes too large." ,
91+ 3 => "Target length is 3 bytes too large." ,
92+ 4 => "Target length is 4 bytes too large." ,
93+ _ => "Target length is more than 4 bytes too large." ,
94+ } ;
95+ panic ! ( "{}" , msg)
96+ }
97+ if to. len ( ) != len {
98+ panic ! ( "Target slice length differs to the specified length." )
99+ }
100+
101+ let mut i = 0 ;
102+ while i < len {
103+ to[ i] = from[ i] ;
104+ i += 1 ;
105+ }
106+ }
107+
108+ const fn bytes_to_array < const N : usize > ( bytes : & [ u8 ] ) -> [ u8 ; N ] {
109+ let mut arr = [ 0u8 ; N ] ;
110+ copy_bytes_to_array ( & mut arr, bytes, N ) ;
111+ arr
112+ }
113+
74114/// For non-de-duplicated string slices stored in `static` variables.
75115pub type NonDeDuplicatedStr < ' from , const N : usize > =
76116 NonDeDuplicatedFlexible < & ' from str , [ u8 ; N ] , str > ;
77117impl < ' from , const N : usize > NonDeDuplicatedStr < ' from , N > {
78118 /// Construct a new instance.
79119 pub const fn new ( s : & str ) -> Self {
80- if s. len ( ) > N {
81- let msg = match s. len ( ) - N {
82- 1 => "N is 1 byte too small." ,
83- 2 => "N is 2 bytes too small." ,
84- 3 => "N is 3 bytes too small." ,
85- 4 => "N is 4 bytes too small." ,
86- _ => "N is more than 4 bytes too small." ,
87- } ;
88- panic ! ( "{}" , msg)
89- }
90- if s. len ( ) < N {
91- let msg = match N - s. len ( ) {
92- 1 => "N is 1 byte too large." ,
93- 2 => "N is 2 bytes too large." ,
94- 3 => "N is 3 bytes too large." ,
95- 4 => "N is 4 bytes too large." ,
96- _ => "N is more than 4 bytes too large." ,
97- } ;
98- panic ! ( "{}" , msg)
99- }
100- let bytes: & [ u8 ] = s. as_bytes ( ) ;
101- let mut arr = [ 0u8 ; N ] ;
102- let mut i = 0 ;
103- while i < bytes. len ( ) {
104- arr[ i] = bytes[ i] ;
105- i += 1 ;
106- }
107120 Self {
108- cell : Cell :: new ( arr ) ,
121+ cell : Cell :: new ( bytes_to_array ( s . as_bytes ( ) ) ) ,
109122 _f : PhantomData ,
110123 _t : PhantomData ,
111124 }
@@ -114,7 +127,7 @@ impl<'from, const N: usize> NonDeDuplicatedStr<'from, N> {
114127 /// Get a reference.
115128 ///
116129 /// Implementation details: Since this type, and this function, is intended to be used for
117- /// `static` or `const` variables, speed doesn't matter. So, we use [core::str::from_utf8]
130+ /// `static` variables only , speed doesn't matter here . So, we use [core::str::from_utf8]
118131 /// (instead of [core::str::from_utf8_unchecked]).
119132 pub const fn get ( & self ) -> & str {
120133 let ptr = self . cell . as_ptr ( ) ;
@@ -126,6 +139,34 @@ impl<'from, const N: usize> NonDeDuplicatedStr<'from, N> {
126139 }
127140}
128141
142+ /// For non-de-duplicated string slices stored in `static` variables.
143+ pub type NonDeDuplicatedCStr < ' from , const N : usize > =
144+ NonDeDuplicatedFlexible < & ' from CStr , [ u8 ; N ] , CStr > ;
145+ impl < ' from , const N : usize > NonDeDuplicatedCStr < ' from , N > {
146+ /// Construct a new instance.
147+ pub const fn new ( s : & CStr ) -> Self {
148+ Self {
149+ cell : Cell :: new ( bytes_to_array ( s. to_bytes ( ) ) ) ,
150+ _f : PhantomData ,
151+ _t : PhantomData ,
152+ }
153+ }
154+
155+ /// Get a reference.
156+ ///
157+ /// Implementation details: Since this type, and this function, is intended to be used for
158+ /// `static` variables only, speed doesn't matter here. So, we use [CStr::from_bytes_with_nul]
159+ /// (instead of [CStr::from_bytes_with_nul_unchecked]).
160+ pub const fn get ( & self ) -> & CStr {
161+ let ptr = self . cell . as_ptr ( ) ;
162+ let bytes = unsafe { & * ptr } ;
163+ match CStr :: from_bytes_with_nul ( bytes) {
164+ Ok ( s) => s,
165+ Err ( _) => unreachable ! ( ) ,
166+ }
167+ }
168+ }
169+
129170/// For now, [Sync] (and [NonDeDuplicatedFlexible] in general) requires that `OWN` is both [Sync]
130171/// AND [Send], following
131172/// [std::sync::Mutex](https://doc.rust-lang.org/nightly/std/sync/struct.Mutex.html#impl-Sync-for-Mutex%3CT%3E).
0 commit comments