Advertisement
Guest User

Untitled

a guest
Jul 16th, 2019
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.49 KB | None | 0 0
  1. use ::std::{*,
  2. borrow::Cow,
  3. convert::Infallible,
  4. ffi::{
  5. CStr,
  6. CString,
  7. },
  8. };
  9.  
  10. #[derive(Debug)]
  11. pub
  12. struct InnerNullError {
  13. pub null_position: usize,
  14. }
  15.  
  16. impl error::Error for InnerNullError {}
  17. impl fmt::Display for InnerNullError {
  18. fn fmt (
  19. self: &'_ Self,
  20. stream: &'_ mut fmt::Formatter<'_>,
  21. ) -> fmt::Result
  22. {
  23. write!(stream, concat!(
  24. "Conversion to C string failed: ",
  25. "inner null byte at position {}.",
  26. ), self.null_position)
  27. }
  28. }
  29.  
  30. pub trait Str<'a> {
  31. type Err : error::Error;
  32.  
  33. fn try_into_cstr (
  34. self: Self
  35. ) -> Result<Cow<'a, CStr>, Self::Err>;
  36. }
  37.  
  38. impl<'a> Str<'a> for &'a CStr {
  39. type Err = Infallible;
  40.  
  41. #[inline]
  42. fn try_into_cstr (
  43. self: Self
  44. ) -> Result<Cow<'a, CStr>, Self::Err>
  45. {
  46. Ok(self.into())
  47. }
  48. }
  49.  
  50. impl<'a> Str<'a> for String {
  51. type Err = InnerNullError;
  52.  
  53. fn try_into_cstr (
  54. self: Self
  55. ) -> Result<Cow<'a, CStr>, Self::Err>
  56. {
  57. match CString::new(self) {
  58. | Ok(c_string) => Ok(c_string.into()),
  59. | Err(nul_error) => Err(InnerNullError {
  60. null_position: nul_error.nul_position(),
  61. }),
  62. }
  63. }
  64. }
  65.  
  66. impl<'a> Str<'a> for &'a str {
  67. type Err = InnerNullError;
  68.  
  69. fn try_into_cstr (
  70. self: Self
  71. ) -> Result<Cow<'a, CStr>, Self::Err>
  72. {
  73. match self.bytes().position(|x| x == b'\0') {
  74. | None
  75. => unsafe {
  76. Ok(CString::from_vec_unchecked(
  77. self.bytes()
  78. .chain(iter::once(b'\0'))
  79. .collect()
  80. ).into())
  81. },
  82.  
  83. | Some(null_position)
  84. if null_position == self.len() - 1
  85. => unsafe {
  86. Ok(CStr::from_bytes_with_nul_unchecked(
  87. self.as_bytes()
  88. ).into())
  89. },
  90.  
  91. | Some(null_position)
  92. => {
  93. Err(InnerNullError {
  94. null_position,
  95. })
  96. },
  97. }
  98. }
  99. }
  100.  
  101. fn puts<'s> (s: impl Str<'s>)
  102. {
  103. let c_str =
  104. s .try_into_cstr()
  105. .unwrap_or_else(|err| panic!("{}", err))
  106. ;
  107. unsafe {
  108. ::libc::puts(c_str.as_ptr());
  109. }
  110. }
  111.  
  112. fn main ()
  113. {
  114. puts("Hello, World!"); // to_owned()
  115. puts("Hello, World!".to_string()); // push()
  116. puts("Hello, World!\0"); // cast
  117. puts("Hell\0, World!"); // panic with nice error message
  118. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement