Reorganize
This commit is contained in:
parent
52b4984945
commit
f0b3d5166e
13 changed files with 378 additions and 286 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/target
|
||||
**/*.rs.bk
|
||||
target
|
||||
*.rs.bk
|
||||
|
|
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -9,6 +9,13 @@ checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
|
|||
[[package]]
|
||||
name = "neco"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"safe_libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "safe_libc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
|
|
@ -5,7 +5,7 @@ authors = ["Matthias Schiffer <mschiffer@universe-factory.net>"]
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
libc = { version = "0.2.68", default-features = false }
|
||||
safe_libc = { path = "safe_libc" }
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
|
14
safe_libc/Cargo.lock
generated
Normal file
14
safe_libc/Cargo.lock
generated
Normal file
|
@ -0,0 +1,14 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
|
||||
|
||||
[[package]]
|
||||
name = "safe_libc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
10
safe_libc/Cargo.toml
Normal file
10
safe_libc/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "safe_libc"
|
||||
version = "0.1.0"
|
||||
authors = ["Matthias Schiffer <mschiffer@universe-factory.net>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
libc = { version = "0.2.68", default-features = false }
|
146
safe_libc/src/boxed.rs
Normal file
146
safe_libc/src/boxed.rs
Normal file
|
@ -0,0 +1,146 @@
|
|||
use crate::util;
|
||||
|
||||
use core::{mem, ptr};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
fn alloc<T>(len: usize) -> *mut T {
|
||||
if util::zst::<T>(len) {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
let size = len.checked_mul(mem::size_of::<T>()).expect("allocation overflow");
|
||||
let align = mem::align_of::<T>();
|
||||
util::must_succeed(
|
||||
unsafe {
|
||||
libc::memalign(align as libc::size_t, size as libc::size_t) as *mut T
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn dangling<T>() -> *mut T {
|
||||
mem::align_of::<T>() as *mut T
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slice_len<T>(p: *const [T]) -> usize {
|
||||
unsafe { mem::transmute::<*const [T], [usize; 2]>(p)[1] }
|
||||
}
|
||||
|
||||
pub struct CBox<T: ?Sized>(*mut T);
|
||||
|
||||
impl<T: ?Sized> CBox<T> {
|
||||
#[inline]
|
||||
pub unsafe fn from_raw_unchecked(p: *mut T) -> CBox<T> {
|
||||
CBox(p)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_raw(self) -> *mut T {
|
||||
let p = self.0;
|
||||
mem::forget(self);
|
||||
p
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *const T {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_mut_ptr(&mut self) -> *mut T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CBox<T> {
|
||||
#[inline]
|
||||
pub fn new(value: T) -> CBox<T> {
|
||||
let p = alloc(1);
|
||||
unsafe {
|
||||
ptr::write(p, value);
|
||||
CBox::from_raw_unchecked(p)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn from_raw(p: *mut T) -> CBox<T> {
|
||||
util::check_ptr(p, 1);
|
||||
CBox(p)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn slice_from_raw_parts_unchecked(p: *mut T, len: usize) -> CBox<[T]> {
|
||||
CBox(ptr::slice_from_raw_parts_mut(p, len))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn slice_from_raw_parts(p: *mut T, len: usize) -> CBox<[T]> {
|
||||
util::check_ptr(p, len);
|
||||
CBox::slice_from_raw_parts_unchecked(p, len)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn safe_ptr(&self) -> *mut T {
|
||||
if util::zst::<T>(1) {
|
||||
return dangling();
|
||||
}
|
||||
|
||||
debug_assert!(!self.0.is_null(), "NULL ptr");
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CBox<[T]> {
|
||||
#[inline]
|
||||
fn safe_ptr(&self) -> *mut [T] {
|
||||
if self.0.is_null() {
|
||||
let len = slice_len(self.0);
|
||||
debug_assert!(util::zst::<T>(len), "NULL ptr");
|
||||
return ptr::slice_from_raw_parts_mut(dangling(), len);
|
||||
}
|
||||
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Drop for CBox<T> {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ptr::drop_in_place(self.0);
|
||||
libc::free(self.0 as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for CBox<T> {
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { &*self.safe_ptr() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for CBox<T> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { &mut *self.safe_ptr() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for CBox<[T]> {
|
||||
type Target = [T];
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &[T] {
|
||||
unsafe { &*self.safe_ptr() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for CBox<[T]> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut [T] {
|
||||
unsafe { &mut *self.safe_ptr() }
|
||||
}
|
||||
}
|
|
@ -1,3 +1,14 @@
|
|||
#![no_std]
|
||||
|
||||
pub use libc::*;
|
||||
|
||||
mod util;
|
||||
|
||||
pub mod boxed;
|
||||
pub mod stdio;
|
||||
pub mod string;
|
||||
|
||||
|
||||
extern "C" {
|
||||
pub fn strndup(cs: *const libc::c_char, n: libc::size_t) -> *mut libc::c_char;
|
||||
|
|
@ -1,21 +1,24 @@
|
|||
use core::fmt;
|
||||
use crate as libc;
|
||||
use crate::string;
|
||||
|
||||
use super::posix;
|
||||
use super::string;
|
||||
use core::fmt;
|
||||
|
||||
pub struct OStream {
|
||||
file: *mut libc::FILE
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn stdout() -> OStream {
|
||||
OStream { file: posix::stdout }
|
||||
OStream { file: libc::stdout }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn stderr() -> OStream {
|
||||
OStream { file: posix::stderr }
|
||||
OStream { file: libc::stderr }
|
||||
}
|
||||
|
||||
impl OStream {
|
||||
#[inline]
|
||||
pub fn write(&mut self, b: &[u8]) {
|
||||
unsafe {
|
||||
libc::fwrite(
|
||||
|
@ -27,6 +30,7 @@ impl OStream {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn puts(&mut self, s: &string::CStr) {
|
||||
unsafe {
|
||||
libc::fputs(s.as_ptr(), self.file);
|
||||
|
@ -35,6 +39,7 @@ impl OStream {
|
|||
}
|
||||
|
||||
impl fmt::Write for OStream {
|
||||
#[inline]
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
self.write(s.as_bytes());
|
||||
Ok(())
|
151
safe_libc/src/string.rs
Normal file
151
safe_libc/src/string.rs
Normal file
|
@ -0,0 +1,151 @@
|
|||
use crate as libc;
|
||||
use crate::util;
|
||||
use crate::boxed::CBox;
|
||||
|
||||
use core::slice;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
//pub struct FromBytesWithNulError {}
|
||||
|
||||
pub struct CStr { inner: libc::c_char }
|
||||
|
||||
impl CStr {
|
||||
#[inline]
|
||||
pub unsafe fn from_ptr_unchecked<'a>(p: *const libc::c_char) -> &'a CStr {
|
||||
&*(p as *const CStr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn from_ptr<'a>(p: *const libc::c_char) -> &'a CStr {
|
||||
util::check_ptr(p, 1);
|
||||
CStr::from_ptr_unchecked(p)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn from_mut_ptr_unchecked<'a>(p: *mut libc::c_char) -> &'a mut CStr {
|
||||
&mut *(p as *mut CStr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn from_mut_ptr<'a>(p: *mut libc::c_char) -> &'a mut CStr {
|
||||
util::check_ptr(p, 1);
|
||||
CStr::from_mut_ptr_unchecked(p)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
|
||||
CStr::from_ptr_unchecked(bytes.as_ptr() as *const libc::c_char)
|
||||
}
|
||||
|
||||
// TODO
|
||||
//pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> {
|
||||
//}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { libc::strlen(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn as_ptr(&self) -> *const libc::c_char {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
|
||||
&mut self.inner
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(
|
||||
self.as_ptr() as *const u8,
|
||||
self.len(),
|
||||
) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_mut_bytes(&mut self) -> &mut [u8] {
|
||||
unsafe { slice::from_raw_parts_mut(
|
||||
self.as_mut_ptr() as *mut u8,
|
||||
self.len(),
|
||||
) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_owned(self: &CStr) -> CString {
|
||||
CString::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! cstr {
|
||||
($s:expr) => (
|
||||
unsafe { $crate::string::CStr::from_bytes_with_nul_unchecked(concat!($s, "\0").as_bytes()) }
|
||||
)
|
||||
}
|
||||
|
||||
pub struct CString { inner: CBox<libc::c_char> }
|
||||
|
||||
impl CString {
|
||||
#[inline]
|
||||
pub unsafe fn from_raw_unchecked(p: *mut libc::c_char) -> CString {
|
||||
CString { inner: CBox::from_raw_unchecked(p) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn from_raw(p: *mut libc::c_char) -> CString {
|
||||
util::check_ptr(p, 1);
|
||||
CString::from_raw_unchecked(p)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_raw(self) -> *mut libc::c_char {
|
||||
self.inner.into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for CString {
|
||||
type Target = CStr;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &CStr {
|
||||
unsafe { CStr::from_ptr(&*self.inner) }
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for CString {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut CStr {
|
||||
unsafe { CStr::from_mut_ptr(&mut *self.inner) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u8]> for CString {
|
||||
fn from(s: &[u8]) -> CString {
|
||||
unsafe {
|
||||
CString::from_raw_unchecked(
|
||||
util::must_succeed(libc::strndup(
|
||||
s.as_ptr() as *const libc::c_char,
|
||||
s.len() as libc::size_t,
|
||||
))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for CString {
|
||||
#[inline]
|
||||
fn from(s: &str) -> CString {
|
||||
CString::from(s.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&CStr> for CString {
|
||||
#[inline]
|
||||
fn from(s: &CStr) -> CString {
|
||||
unsafe {
|
||||
CString::from_raw_unchecked(util::must_succeed(libc::strdup(s.as_ptr())))
|
||||
}
|
||||
}
|
||||
}
|
18
safe_libc/src/util.rs
Normal file
18
safe_libc/src/util.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
use core::mem;
|
||||
|
||||
#[inline]
|
||||
pub fn zst<T>(len: usize) -> bool {
|
||||
mem::size_of::<T>() == 0 || len == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn check_ptr<T>(p: *const T, len: usize) {
|
||||
debug_assert!((p as usize) % mem::align_of::<T>() == 0, "unaligned ptr");
|
||||
assert!(zst::<T>(len) || !p.is_null(), "NULL ptr");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn must_succeed<T>(p: *mut T) -> *mut T {
|
||||
assert!(!p.is_null(), "allocation failure");
|
||||
p
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
pub mod posix;
|
||||
pub mod stdio;
|
||||
pub mod string;
|
266
src/c/string.rs
266
src/c/string.rs
|
@ -1,266 +0,0 @@
|
|||
use super::posix;
|
||||
use core::{mem, ptr, slice};
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
fn must_succeed<T>(p: *mut T) -> *mut T {
|
||||
assert!(!p.is_null(), "allocation failure");
|
||||
p
|
||||
}
|
||||
|
||||
fn zst<T>(count: usize) -> bool {
|
||||
mem::size_of::<T>() == 0 || count == 0
|
||||
}
|
||||
|
||||
fn alloc<T>(count: usize) -> *mut T {
|
||||
if zst::<T>(count) {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
let size = count * mem::size_of::<T>();
|
||||
let align = mem::align_of::<T>();
|
||||
must_succeed(
|
||||
unsafe {
|
||||
libc::memalign(align as libc::size_t, size as libc::size_t) as *mut T
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn dangling<T>() -> *mut T {
|
||||
mem::align_of::<T>() as *mut T
|
||||
}
|
||||
|
||||
fn check_ptr<T>(p: *const T, len: usize) {
|
||||
debug_assert!((p as usize) % mem::align_of::<T>() == 0, "unaligned ptr");
|
||||
assert!(zst::<T>(len) || !p.is_null(), "NULL ptr");
|
||||
}
|
||||
|
||||
fn slice_len<T>(p: *const [T]) -> usize {
|
||||
unsafe { mem::transmute::<*const [T], [usize; 2]>(p)[1] }
|
||||
}
|
||||
|
||||
pub struct CBox<T: ?Sized>(*mut T);
|
||||
|
||||
impl<T: ?Sized> CBox<T> {
|
||||
pub unsafe fn from_raw_unchecked(p: *mut T) -> CBox<T> {
|
||||
CBox(p)
|
||||
}
|
||||
|
||||
pub fn into_raw(self) -> *mut T {
|
||||
let p = self.0;
|
||||
mem::forget(self);
|
||||
p
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *const T {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn as_mut_ptr(&mut self) -> *mut T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CBox<T> {
|
||||
pub fn new(value: T) -> CBox<T> {
|
||||
let p = alloc(1);
|
||||
unsafe {
|
||||
ptr::write(p, value);
|
||||
CBox::from_raw_unchecked(p)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn from_raw(p: *mut T) -> CBox<T> {
|
||||
check_ptr(p, 1);
|
||||
CBox(p)
|
||||
}
|
||||
|
||||
pub unsafe fn slice_from_raw_parts_unchecked(p: *mut T, len: usize) -> CBox<[T]> {
|
||||
CBox(ptr::slice_from_raw_parts_mut(p, len))
|
||||
}
|
||||
|
||||
pub unsafe fn slice_from_raw_parts(p: *mut T, len: usize) -> CBox<[T]> {
|
||||
check_ptr(p, len);
|
||||
CBox::slice_from_raw_parts_unchecked(p, len)
|
||||
}
|
||||
|
||||
fn safe_ptr(&self) -> *mut T {
|
||||
if self.0.is_null() {
|
||||
debug_assert!(zst::<T>(1), "NULL ptr");
|
||||
return dangling();
|
||||
}
|
||||
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> CBox<[T]> {
|
||||
fn safe_ptr(&self) -> *mut [T] {
|
||||
if self.0.is_null() {
|
||||
let len = slice_len(self.0);
|
||||
debug_assert!(zst::<T>(len), "NULL ptr");
|
||||
return ptr::slice_from_raw_parts_mut(dangling(), len);
|
||||
}
|
||||
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Drop for CBox<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ptr::drop_in_place(self.0);
|
||||
libc::free(self.0 as *mut libc::c_void);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for CBox<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { &*self.safe_ptr() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for CBox<T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { &mut *self.safe_ptr() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for CBox<[T]> {
|
||||
type Target = [T];
|
||||
|
||||
fn deref(&self) -> &[T] {
|
||||
unsafe { &*self.safe_ptr() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for CBox<[T]> {
|
||||
fn deref_mut(&mut self) -> &mut [T] {
|
||||
unsafe { &mut *self.safe_ptr() }
|
||||
}
|
||||
}
|
||||
|
||||
//pub struct FromBytesWithNulError {}
|
||||
|
||||
pub struct CStr { inner: libc::c_char }
|
||||
|
||||
impl CStr {
|
||||
pub unsafe fn from_ptr_unchecked<'a>(p: *const libc::c_char) -> &'a CStr {
|
||||
&*(p as *const CStr)
|
||||
}
|
||||
|
||||
pub unsafe fn from_ptr<'a>(p: *const libc::c_char) -> &'a CStr {
|
||||
check_ptr(p, 1);
|
||||
CStr::from_ptr_unchecked(p)
|
||||
}
|
||||
|
||||
pub unsafe fn from_mut_ptr_unchecked<'a>(p: *mut libc::c_char) -> &'a mut CStr {
|
||||
&mut *(p as *mut CStr)
|
||||
}
|
||||
|
||||
pub unsafe fn from_mut_ptr<'a>(p: *mut libc::c_char) -> &'a mut CStr {
|
||||
check_ptr(p, 1);
|
||||
CStr::from_mut_ptr_unchecked(p)
|
||||
}
|
||||
|
||||
pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
|
||||
CStr::from_ptr_unchecked(bytes.as_ptr() as *const libc::c_char)
|
||||
}
|
||||
|
||||
// TODO
|
||||
//pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> {
|
||||
//}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { libc::strlen(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
pub const fn as_ptr(&self) -> *const libc::c_char {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
|
||||
&mut self.inner
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(
|
||||
self.as_ptr() as *const u8,
|
||||
self.len(),
|
||||
) }
|
||||
}
|
||||
|
||||
pub fn as_mut_bytes(&mut self) -> &mut [u8] {
|
||||
unsafe { slice::from_raw_parts_mut(
|
||||
self.as_mut_ptr() as *mut u8,
|
||||
self.len(),
|
||||
) }
|
||||
}
|
||||
|
||||
pub fn to_owned(self: &CStr) -> CString {
|
||||
CString::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! cstr {
|
||||
($s:expr) => (
|
||||
unsafe { $crate::c::string::CStr::from_bytes_with_nul_unchecked(concat!($s, "\0").as_bytes()) }
|
||||
)
|
||||
}
|
||||
|
||||
pub struct CString { inner: CBox<libc::c_char> }
|
||||
|
||||
impl CString {
|
||||
pub unsafe fn from_raw_unchecked(p: *mut libc::c_char) -> CString {
|
||||
CString { inner: CBox::from_raw_unchecked(p) }
|
||||
}
|
||||
|
||||
pub unsafe fn from_raw(p: *mut libc::c_char) -> CString {
|
||||
CString { inner: CBox::from_raw(p) }
|
||||
}
|
||||
|
||||
pub fn into_raw(self) -> *mut libc::c_char {
|
||||
self.inner.into_raw()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for CString {
|
||||
type Target = CStr;
|
||||
|
||||
fn deref(&self) -> &CStr {
|
||||
unsafe { CStr::from_ptr(&*self.inner) }
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for CString {
|
||||
fn deref_mut(&mut self) -> &mut CStr {
|
||||
unsafe { CStr::from_mut_ptr(&mut *self.inner) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u8]> for CString {
|
||||
fn from(s: &[u8]) -> CString {
|
||||
unsafe {
|
||||
CString::from_raw_unchecked(must_succeed(posix::strndup(
|
||||
s.as_ptr() as *const libc::c_char,
|
||||
s.len() as libc::size_t,
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for CString {
|
||||
fn from(s: &str) -> CString {
|
||||
CString::from(s.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&CStr> for CString {
|
||||
fn from(s: &CStr) -> CString {
|
||||
unsafe {
|
||||
CString::from_raw_unchecked(must_succeed(libc::strdup(s.as_ptr())))
|
||||
}
|
||||
}
|
||||
}
|
17
src/main.rs
17
src/main.rs
|
@ -1,30 +1,29 @@
|
|||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
mod c;
|
||||
use safe_libc as libc;
|
||||
use libc::cstr;
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn main(_nargs: libc::c_int, _args: *const *const libc::c_char) -> libc::c_int {
|
||||
let mut stdout = unsafe { c::stdio::stdout() };
|
||||
let x = c::string::CString::from("foo");
|
||||
let mut stdout = unsafe { libc::stdio::stdout() };
|
||||
let x = libc::string::CString::from("foo");
|
||||
let l = x.len();
|
||||
let y = x.into_raw();
|
||||
let z = unsafe {
|
||||
c::string::CBox::slice_from_raw_parts(y, l)
|
||||
libc::boxed::CBox::slice_from_raw_parts(y, l)
|
||||
};
|
||||
//let y = unsafe { c::string::CBox::from_raw(x) };
|
||||
//let foo = cstr!("Foo! %p\n");
|
||||
//c::stdio::stdout().puts(foo);
|
||||
let foo = cstr!("Foo!\n");
|
||||
stdout.puts(foo);
|
||||
let _ = writeln!(stdout, "Foo: {} {} {}", z[0], z[1], z[2]);
|
||||
0
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &core::panic::PanicInfo) -> ! {
|
||||
let _ = writeln!(unsafe { c::stdio::stderr() }, "Panic: {}", info);
|
||||
let _ = writeln!(unsafe { libc::stdio::stderr() }, "Panic: {}", info);
|
||||
unsafe { libc::abort() }
|
||||
}
|
||||
|
|
Reference in a new issue