Advertisement
Guest User

Untitled

a guest
Jul 16th, 2019
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.44 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. fn try_into_cstr (
  42. self: Self
  43. ) -> Result<Cow<'a, CStr>, Self::Err>
  44. {
  45. Ok(self.into())
  46. }
  47. }
  48.  
  49. impl<'a> Str<'a> for String {
  50. type Err = InnerNullError;
  51.  
  52. fn try_into_cstr (
  53. self: Self
  54. ) -> Result<Cow<'a, CStr>, Self::Err>
  55. {
  56. match CString::new(self) {
  57. | Ok(c_string) => Ok(c_string.into()),
  58. | Err(nul_error) => Err(InnerNullError {
  59. null_position: nul_error.nul_position(),
  60. }),
  61. }
  62. }
  63. }
  64.  
  65. impl<'a> Str<'a> for &'a str {
  66. type Err = InnerNullError;
  67.  
  68. fn try_into_cstr (
  69. self: Self
  70. ) -> Result<Cow<'a, CStr>, Self::Err>
  71. {
  72. match self.as_bytes().iter().position(|x| *x == b'\0') {
  73. | None => unsafe {
  74. Ok(CString::from_vec_unchecked(
  75. self.bytes()
  76. .chain(iter::once(b'\0'))
  77. .collect()
  78. ).into())
  79. },
  80.  
  81. | Some(null_position)
  82. if null_position == self.len() - 1
  83. => unsafe {
  84. Ok(CStr::from_bytes_with_nul_unchecked(
  85. self.as_bytes()
  86. ).into())
  87. },
  88.  
  89. | Some(null_position) => {
  90. Err(InnerNullError {
  91. null_position,
  92. })
  93. },
  94. }
  95. }
  96. }
  97.  
  98. fn puts<'__> (s: impl Str<'__>)
  99. {
  100. let c_str =
  101. s .try_into_cstr()
  102. .unwrap_or_else(|err| panic!("{}", err))
  103. ;
  104. unsafe {
  105. ::libc::puts(c_str.as_ptr());
  106. }
  107. }
  108.  
  109. fn main ()
  110. {
  111. puts("Hello, World!");
  112. puts("Hello, World!".to_string());
  113. puts(CStr::from_bytes_with_nul(b"Hello, World!\0").unwrap());
  114. puts("Hell\0, World!");
  115. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement