@@ -2,7 +2,11 @@ use core::str;
22
33use crate :: error:: { Error , Result } ;
44
5- // A BSON-spec cstring: Zero or more UTF-8 encoded characters, excluding the null byte.
5+ /// A borrowed BSON-spec cstring: Zero or more UTF-8 encoded characters, excluding the nul byte.
6+ /// Most conveniently constructed via the [`cstr!`](crate::raw::cstr) macro.
7+ ///
8+ /// Unlike [`std::ffi::CStr`], this is required to be valid UTF-8, and does not include the nul
9+ /// terminator in the buffer.
610#[ derive( Debug ) ]
711#[ repr( transparent) ]
812pub struct CStr {
@@ -36,15 +40,18 @@ impl CStr {
3640 unsafe { & * ( value. as_bytes ( ) as * const [ u8 ] as * const CStr ) }
3741 }
3842
43+ /// View the buffer as a Rust `&str`.
3944 pub fn as_str ( & self ) -> & str {
4045 // Safety: the only way to constrct a CStr is from a valid &str.
4146 unsafe { str:: from_utf8_unchecked ( & self . data ) }
4247 }
4348
49+ /// The length in bytes of the buffer.
4450 pub fn len ( & self ) -> usize {
4551 self . as_str ( ) . len ( )
4652 }
4753
54+ /// Whether the buffer contains zero bytes.
4855 pub fn is_empty ( & self ) -> bool {
4956 self . as_str ( ) . is_empty ( )
5057 }
@@ -91,11 +98,15 @@ impl serde::Serialize for &CStr {
9198 }
9299}
93100
101+ #[ doc( hidden) ]
94102#[ diagnostic:: on_unimplemented( message = "the string literal contains a zero byte" ) ]
95103pub trait ValidCStr { }
104+ #[ doc( hidden) ]
96105pub struct IsValidCStr < const VALID : bool > ;
106+ #[ doc( hidden) ]
97107impl ValidCStr for IsValidCStr < true > { }
98108
109+ #[ doc( hidden) ]
99110pub const fn validate_cstr ( text : & str ) -> Option < & CStr > {
100111 let bytes = text. as_bytes ( ) ;
101112 let mut i = 0 ;
@@ -107,8 +118,20 @@ pub const fn validate_cstr(text: &str) -> Option<&CStr> {
107118 }
108119 Some ( CStr :: from_str_unchecked ( text) )
109120}
121+ #[ doc( hidden) ]
110122pub const fn assert_valid_cstr < T : ValidCStr > ( ) { }
111123
124+ /// Construct a `'static &CStr`. The validitiy will be verified at compile-time.
125+ /// ```
126+ /// # use bson::raw::{CStr, cstr};
127+ /// // A valid literal:
128+ /// let key: &CStr = cstr!("hello");
129+ /// ```
130+ /// ```compile_fail
131+ /// # use bson::raw::{CStr, cstr};
132+ /// // An invalid literal will not compile:
133+ /// let key: &CStr = cstr!("hel\0lo");
134+ /// ```
112135#[ macro_export]
113136macro_rules! cstr {
114137 ( $text: literal) => { {
@@ -120,6 +143,11 @@ macro_rules! cstr {
120143}
121144pub use cstr;
122145
146+ /// An owned BSON-spec cstring: Zero or more UTF-8 encoded characters, excluding the nul byte.
147+ /// `CString` is to `CStr` as [`String`] is to [`prim@str`].
148+ ///
149+ /// Like `CStr`, this differs from [`std::ffi::CString`] in that it is required to be valid UTF-8,
150+ /// and does not include the nul terminator in the buffer.
123151#[ derive( Clone , Eq , PartialEq , Hash ) ]
124152#[ repr( transparent) ]
125153pub struct CString {
@@ -149,10 +177,12 @@ impl CString {
149177 Self { data }
150178 }
151179
180+ /// Consume `self` to return the underlying `String`.
152181 pub fn into_string ( self ) -> String {
153182 self . data
154183 }
155184
185+ /// View the buffer as a Rust `&str`.
156186 pub fn as_str ( & self ) -> & str {
157187 self . as_ref ( ) . as_str ( )
158188 }
0 commit comments