@@ -702,3 +702,109 @@ fn clone_shared<T: Cowable + ?Sized>(
702702
703703 ( ptr, * metadata)
704704}
705+
706+ /// These implementations should be identical to Deref, but enable dereferencing in a `const`
707+ /// environment for `Key` hashing.
708+ pub ( crate ) mod const_cow {
709+ use super :: * ;
710+ use crate :: Label ;
711+ use std:: ptr:: slice_from_raw_parts;
712+
713+ impl Cow < ' static , str > {
714+ pub ( crate ) const fn as_const_str ( & self ) -> & str {
715+ let borrowed_ptr =
716+ slice_from_raw_parts ( self . ptr . as_ptr ( ) , self . metadata . len ( ) ) as * const str ;
717+
718+ // SAFETY: We only ever hold a pointer to a borrowed value of at least the lifetime of
719+ // `Self`, or an owned value which we have ownership of (albeit indirectly when using
720+ // `Arc<T>`), so our pointer is always valid and live for dereferencing.
721+ //
722+ // self.ptr is also `NonNull<T>`, and so borrowed_ptr is guaranteed to not be null.
723+ unsafe { & * borrowed_ptr }
724+ }
725+ }
726+
727+ impl Cow < ' static , [ Label ] > {
728+ pub ( crate ) const fn as_const_slice ( & self ) -> & [ Label ] {
729+ let borrowed_ptr =
730+ slice_from_raw_parts ( self . ptr . as_ptr ( ) , self . metadata . len ( ) ) as * const [ Label ] ;
731+
732+ // SAFETY: We only ever hold a pointer to a borrowed value of at least the lifetime of
733+ // `Self`, or an owned value which we have ownership of (albeit indirectly when using
734+ // `Arc<T>`), so our pointer is always valid and live for dereferencing.
735+ //
736+ // self.ptr is also `NonNull<T>`, and so borrowed_ptr is guaranteed to not be null.
737+ unsafe { & * borrowed_ptr }
738+ }
739+ }
740+
741+ #[ cfg( test) ]
742+ mod tests {
743+ use super :: * ;
744+ use std:: sync:: Arc ;
745+
746+ #[ test]
747+ fn test_as_const_str ( ) {
748+ // Borrowed
749+ let cow = Cow :: const_str ( "hello" ) ;
750+ assert_eq ! ( cow. as_const_str( ) , "hello" ) ;
751+
752+ // Owned
753+ let cow: Cow < ' static , str > = Cow :: from_owned ( String :: from ( "hello" ) ) ;
754+ assert_eq ! ( cow. as_const_str( ) , "hello" ) ;
755+
756+ // Shared
757+ let arc: Arc < str > = Arc :: from ( "hello" ) ;
758+ let cow: Cow < ' static , str > = Cow :: from_shared ( arc) ;
759+ assert_eq ! ( cow. as_const_str( ) , "hello" ) ;
760+ }
761+
762+ #[ test]
763+ fn test_as_const_slice ( ) {
764+ // Borrowed
765+ {
766+ static LABELS : [ Label ; 2 ] = [
767+ Label :: from_static_parts ( "key1" , "value1" ) ,
768+ Label :: from_static_parts ( "key2" , "value2" ) ,
769+ ] ;
770+ let cow = Cow :: const_slice ( & LABELS ) ;
771+ let slice = cow. as_const_slice ( ) ;
772+ assert_eq ! ( slice. len( ) , 2 ) ;
773+ assert_eq ! ( slice[ 0 ] . key( ) , "key1" ) ;
774+ assert_eq ! ( slice[ 0 ] . value( ) , "value1" ) ;
775+ assert_eq ! ( slice[ 1 ] . key( ) , "key2" ) ;
776+ assert_eq ! ( slice[ 1 ] . value( ) , "value2" ) ;
777+ }
778+
779+ // Owned
780+ {
781+ let labels = vec ! [
782+ Label :: from_static_parts( "key1" , "value1" ) ,
783+ Label :: from_static_parts( "key2" , "value2" ) ,
784+ ] ;
785+ let cow: Cow < ' static , [ Label ] > = Cow :: from_owned ( labels) ;
786+ let slice = cow. as_const_slice ( ) ;
787+ assert_eq ! ( slice. len( ) , 2 ) ;
788+ assert_eq ! ( slice[ 0 ] . key( ) , "key1" ) ;
789+ assert_eq ! ( slice[ 0 ] . value( ) , "value1" ) ;
790+ assert_eq ! ( slice[ 1 ] . key( ) , "key2" ) ;
791+ assert_eq ! ( slice[ 1 ] . value( ) , "value2" ) ;
792+ }
793+
794+ // Shared
795+ {
796+ let labels: Arc < [ Label ] > = Arc :: from ( [
797+ Label :: from_static_parts ( "key1" , "value1" ) ,
798+ Label :: from_static_parts ( "key2" , "value2" ) ,
799+ ] ) ;
800+ let cow: Cow < ' static , [ Label ] > = Cow :: from_shared ( labels) ;
801+ let slice = cow. as_const_slice ( ) ;
802+ assert_eq ! ( slice. len( ) , 2 ) ;
803+ assert_eq ! ( slice[ 0 ] . key( ) , "key1" ) ;
804+ assert_eq ! ( slice[ 0 ] . value( ) , "value1" ) ;
805+ assert_eq ! ( slice[ 1 ] . key( ) , "key2" ) ;
806+ assert_eq ! ( slice[ 1 ] . value( ) , "value2" ) ;
807+ }
808+ }
809+ }
810+ }
0 commit comments