I'm playing with Nickel.rs to build a todo list example. As closures are not supported for the moment, I am trying to find another way deal with the simple structure I implemented.
Here is my code :
extern crate nickel;
use std::io::net::ip::Ipv4Addr;
use nickel::{Nickel, Request, Response};
struct TaskList {
list: Vec<String>
}
impl TaskList {
fn new() -> TaskList {
TaskList { list: Vec::new() }
}
fn add_task (&mut self, task: &str) {
&self.list.push(task.to_string());
}
fn get_tasks (&self) -> Vec<String> {
self.list.to_vec()
}
}
fn main() {
let mut server = Nickel::new();
static mut sample : TaskList = TaskList { list: Vec::new() };
sample.add_task("First");
sample.add_task("Second");
fn fetch_tasks (_request: &Request, response: &mut Response) {
response.send(sample.get_tasks().to_string())
}
server.utilize(Nickel::static_files("./public"));
server.get("/task", fetch_tasks);
server.listen(Ipv4Addr(127, 0, 0, 1), 6767);
}
But the compiler write me this : "mutable static items are not allowed to have destructors"
Do you have any advice on how I can solve this ?
I'm not really sure what you're trying to achieve.
If you want the TaskList to exist on the heap, use Box. However, stack scope should be valid event inside server.listen(), so I don't see why you'd need TaskList to be a static mut?
If you want to mess around with static variables, you have to do it unsafely, like this:
use std::mem::transmute;
use std::ptr;
struct Static {
v: int
}
impl Static {
fn whatever(&mut self) {
println!("Write to static");
self.v += 1;
}
}
static mut _data:*const Static = 0 as *const Static;
unsafe fn get<'a>() -> &'a mut Static {
if _data == ptr::null::<Static>() {
// Notice this is a Box<Static>, which is a *Static allocated on the heap
// transmute(Static { v: 0 }) wouldn't work because once the stack scope ends
// the instance would no longer be valid; Box<T> lasts beyond the call to get()
_data = transmute(box Static { v: 0 });
}
return transmute(_data);
}
unsafe fn release() {
ptr::read::<Static>(_data);
}
impl Drop for Static {
fn drop(&mut self) {
println!("Dropped static");
}
}
fn main() {
unsafe {
let foo = get();
foo.whatever();
}
unsafe {
let foo = get();
foo.whatever();
}
unsafe {
release();
}
println!("Done");
}
I really strongly recommend against it though, unless there's a very good reason.
Most of the time you can assume the a variable you create in one scope:
{
let foo = Bar;
...
} <-- End
Will continue to be valid until the end of that scope.
A sub call like server.get is still inside the main() { } scope where sample is defined.
It'll still be valid.
Related
I have tried to create a small readline wrapper for Rust, however, it does not work - I have tried to expose the functionality to free and remove history items, as well as to write history to a file. Nothing happens when I call the functions, i.e., the entries I wanted to delete are still there. Write to file function does not work too, the file is not even being created or modified.
Here's what I've done:
use errno::errno;
use libc::c_void;
use std::{ffi::CString, fmt, path::Path, ptr};
mod ext_readline {
use libc::{c_char, c_int, c_void};
#[repr(C)]
pub struct HistoryEntry {
pub line: *const c_char,
pub data: *mut c_void,
}
#[link(name = "readline")]
extern "C" {
pub fn remove_history(which: c_int) -> *mut HistoryEntry;
pub fn free_history_entry(entry: *mut HistoryEntry) -> *mut c_void;
pub fn write_history(file: *const c_char) -> c_int;
}
}
pub fn remove<'a>(offset: i32) -> &'a mut ext_readline::HistoryEntry {
unsafe { &mut *ext_readline::remove_history(offset) }
}
pub fn free_entry(entry: &mut ext_readline::HistoryEntry) -> Result<(), *mut c_void> {
unsafe {
let data_ptr = ext_readline::free_history_entry(entry);
if data_ptr.is_null() {
Ok(())
} else {
Err(data_ptr)
}
}
}
pub fn write(path: Option<&Path>) -> Result<i32, HistoryError> {
with_path_ptr(path, |ptr| unsafe {
gen_result(ext_readline::write_history(ptr))
})
}
fn with_path_ptr<F>(path: Option<&Path>, f: F) -> Result<i32, HistoryError>
where
F: Fn(*const i8) -> Result<i32, HistoryError>,
{
if let Some(p) = path {
match p.to_str() {
Some(p) => {
if let Ok(cs) = CString::new(p) {
return f(cs.as_ptr());
}
}
None => {
return Err(HistoryError::new(
"History Error",
"Unable to determine path!",
))
}
}
}
f(ptr::null())
}
fn gen_result(res: i32) -> Result<i32, HistoryError> {
if res == 0 {
Ok(res)
} else {
let e = errno();
let code = e.0 as i32;
let out = format!("Error {}: {}", code, e);
Err(HistoryError::new("History Error", &out[..]))
}
}
#[derive(Debug)]
/// Represents an error that has occurred within the History API.
pub struct HistoryError {
desc: String,
detail: String,
}
impl HistoryError {
/// Create a HistoryError struct from the given description and detail.
pub fn new<T>(desc: &str, detail: T) -> HistoryError
where
T: fmt::Display,
{
HistoryError {
desc: String::from(desc),
detail: format!("{}", detail),
}
}
}
/// Implemented as 'self.desc: self.detail'.
impl fmt::Display for HistoryError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {}", self.desc, self.detail)
}
}
impl From<::std::ffi::NulError> for HistoryError {
fn from(e: ::std::ffi::NulError) -> HistoryError {
HistoryError::new("NulError", e)
}
}
impl From<::std::str::Utf8Error> for HistoryError {
fn from(e: ::std::str::Utf8Error) -> HistoryError {
HistoryError::new("FromUtf8Error", e)
}
}
impl From<::std::num::ParseIntError> for HistoryError {
fn from(e: ::std::num::ParseIntError) -> HistoryError {
HistoryError::new("ParseIntError", e)
}
}
How can I overcome the issue?
I have a C library with a lot of callbacks in the form
void asynchronous_thing(..., void* userInfo, SOMECBTYPE cb)
I am writing unit tests for these in Swift/XCT, and am wondering what the best solution to pass vars into the closure that Xcode/Swift generates for me automatically (I am providing one answer but my Swift is sub-par, so chances are high there is a much more elegant way to do this).
This is the solution I have:
class CUserInfoClass<T> {
let v: T
init(_ v: T) {
self.v = v
}
init(_ userInfo: UnsafeMutableRawPointer) {
self.v = CUserInfoCallback<T>(userInfo).v.v
}
}
class CExpectation : CUserInfoClass<XCTestExpectation> {
func fulfill() {
self.v.fulfill()
}
}
class CUserInfoCallback<T> {
let v: CUserInfoClass<T>
init(_ v: CUserInfoClass<T>) {
self.v = v
}
init(_ userInfo: UnsafeMutableRawPointer) {
self.v = Unmanaged<CUserInfoClass<T>>.fromOpaque(userInfo).takeUnretainedValue()
}
func wrap() -> UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(Unmanaged.passUnretained(self.v).toOpaque())
}
}
I use this in the following manner:
func testAsyncThingie() {
let exp = CUserInfoCallback(CUserInfoClass(expectation(description: "Wait for async thingie")))
DoAsyncThing(exp.wrap()) {
(ui, err) in
XCTAssertNil(err)
CExpectation(ui!).fulfill()
}
waitForExpectations(timeout: 10, handler: nil)
}
where DoAsyncThing is
void DoAsyncThing(void*, void (*)(void* userInfo, const char* error))
I have an struct with a refence to an array of type T:
pub struct myStruct<'a, T> {
pub data: &'a [T],
}
I want to modify one element of this array and check the result of an operation. for that I am trying to copy the array, modify the value and execute the operation:
pub fn check_value(&self, data: &T, position: usize) -> bool {
if position >= self.data.len() {
return false;
}
let array_temp = Box::new(self.data);
array_temp[position] = *data;
return mycheck(array_temp);
}
I am getting this error:
error[E0594]: cannot assign to `array_temp[_]` which is behind a `&` reference
I would like to know how to copy the array and modify the value or just modify directly the value in the original array (data) and restore the original value later.
Here you have a complete code to compile
pub struct MyStruct<'a, T> {
pub data: &'a [T],
}
impl<'a, T> MyStruct<'a, T>
where
T: Copy,
{
fn mycheck(&self, myarray: &[T]) -> bool {
if myarray.len() > 0 {
return true;
} else {
return false;
}
}
pub fn check_value(&self, data: &T, position: usize) -> bool {
if position >= self.data.len() {
return false;
}
let array_temp = Box::new(self.data);
array_temp[position] = *data;
return self.mycheck(&array_temp);
}
}
fn main() {
println!("Hello World!");
}
You do not have an array (whose length is known), but you have a slice (whose length is not known at compile time). Thus, you must adjust to the dynamic length.
You probably want to use self.data.to_vec() instead of Box::new(self.data).
to_vec copies the values into a newly allocated vector having enough capacity.
I have an external library (e.g. libcisland.so) with interface like this:
size_t lib_handle_size();
typedef void* handle;
int lib_init(handle h);
int lib_store(handle h, int value);
int lib_restore(handle h, int *pvalue);
The user of this library is expected to do following:
// allocate some buffer in client address space
handle h = malloc(lib_handle_size());
// pass this buffer to library for initialization
if (lib_init(h)) { /* handle errors */ }
// library initializes this handle by some opaque fashion
// then user uses it
lib_store(h,42);
int r;
lib_restore(h,&r);
// after all work is done, user frees this handle
free(h);
I can't figure out how to properly wrap this interface to Rust.
This is what I ended up:
pub struct Island {
h: Handle,
v: Vec<u8>,
}
impl Island {
pub fn new() -> Island {
let len = unsafe { lib_handle_size() };
let mut v: Vec<u8> = Vec::with_capacity(len);
let h: Handle = v.as_mut_ptr();
Island { v:v, h:h, }
}
pub fn store(&mut self, v: i32) {
unsafe { lib_store(self.h, v); }
}
pub fn restore(&mut self) -> i32 {
let mut v = 0;
unsafe { lib_restore(self.h, &mut v); }
v
}
}
impl Drop for Island {
fn drop(&mut self) {
drop(&mut self.v);
}
}
/// unsafe part
use libc::size_t;
pub type Handle = *mut u8;
#[link(name="cisland")]
extern {
pub fn lib_handle_size() -> size_t;
pub fn lib_init(h: Handle) -> i32;
pub fn lib_store(h: Handle, value: i32) -> i32;
pub fn lib_restore(h: Handle, pvalue: &mut i32) -> i32;
}
Is it Ok to use Vec(u8) for this purpose? Is this Drop trait implemented properly?
Is it Ok to use Vec(u8) for this purpose?
I think Vec<u8> is ok, but you should initialize it rather than using a zero-length vector, pointing at uninitialized memory. It would also be more robust to use Box<[u8]> because that will enforce that it can't be reallocated accidentally.
Is this Drop trait implemented properly?
It should not be necessary to implement Drop at all. The fields of Island each will drop correctly anyway.
Rather than store the handle, I would get it each time using a method. Then your struct is much simpler.
use libc::c_void;
pub struct Island {
buf: Box<[u8]>,
}
impl Island {
pub fn new() -> Island {
let len = unsafe { lib_handle_size() };
let v: Vec<u8> = vec![0; len];
Island { buf: v.into_boxed_slice() }
}
pub fn store(&mut self, v: i32) {
unsafe { lib_store(self.handle_mut(), v); }
}
pub fn restore(&mut self) -> i32 {
let mut v = 0;
unsafe { lib_restore(self.handle_mut(), &mut v); }
v
}
fn handle_mut(&mut self) -> *mut c_void {
self.buf.as_mut_ptr() as *mut c_void
}
}
You don't need a Drop implementation because the Box will drop automatically when it goes out of scope (as would a Vec).
Is it Ok to use Vec(u8) for this purpose?
A vector is not mean to be use like that, even if your code should work this is not a good method.
To do it properly you need an experimental feature (this one is quite stable), you need to use System structure and Alloc trait. Unfortunately, your library doesn't give any alignment requirement for its handle so we must use 1.
pub type Handle = *mut u8; is incorrect according to your typedef void* handle; (by the way hide pointer is bad). It should be pub type Handle = *mut libc::c_void;.
#![feature(allocator_api)]
use std::alloc::{Alloc, Layout, System};
use std::ptr::NonNull;
pub struct Island {
handle: NonNull<u8>,
layout: Layout,
}
impl Island {
pub fn new() -> Island {
let size = unsafe { lib_handle_size() };
let layout = Layout::from_size_align(size, 1).unwrap();
let handle = unsafe { System.alloc(layout).unwrap() };
unsafe {
// can have error I guess ?
lib_init(handle.as_ptr() as Handle);
}
Self { handle, layout }
}
pub fn store(&mut self, v: i32) -> Result<(), ()> {
unsafe {
lib_store(self.handle.as_ptr() as Handle, v);
}
Ok(())
}
pub fn restore(&mut self, v: &mut i32) -> Result<(), ()> {
unsafe {
lib_restore(self.handle.as_ptr() as Handle, v);
}
Ok(())
}
}
impl Drop for Island {
fn drop(&mut self) {
unsafe { System.dealloc(self.handle, self.layout) }
}
}
/// unsafe part
use libc::size_t;
pub type Handle = *mut libc::c_void;
#[link(name = "cisland")]
extern "C" {
pub fn lib_handle_size() -> size_t;
pub fn lib_init(h: Handle) -> i32;
pub fn lib_store(h: Handle, value: i32) -> i32;
pub fn lib_restore(h: Handle, pvalue: &mut i32) -> i32;
}
I change a little bit your store() and restore() function to return an Result. I bet your C function do the same.
I am trying to write a parser that passes an iterator over a vector to a function. The code is similar to this:
fn foo(itr : ???) {
while let Some(c) = itr.next() {
if *c != 0 {
break;
}
println!("{}", *c);
}
}
fn main() {
let v = vec![0; 10];
let itr = v.iter();
while let Some(c) = itr.next() {
foo(itr);
}
}
I am not sure how to write the type of the iterator over the vector. I tried putting the wrong type u32 to see what type rustc expected: core::slice::Iter<'_, _>. When I try to use core::slice rustc complains Use of undeclared type or module 'core::slice'
There are many types of iterators; most of the time, what you really want is a function that is able to consume any of them. To do this, the idiomatic solution is to use generics.
fn foo<'a, T: Iterator<Item=&'a i32>>(mut itr: T) {
while let Some(c) = itr.next() {
if *c != 0 {
break;
}
println!("{}", *c);
}
}
fn main() {
let v = vec![0; 10];
let mut itr = v.iter();
while let Some(c) = itr.next() {
foo(itr);
}
}
The code above doesn't compile though, since it moves itr into foo, then tries to use it again on the while let. To solve this, we need to pass the iterator by reference instead.
fn foo<'a, T: Iterator<Item=&'a i32>>(itr: &mut T) {
while let Some(c) = itr.next() {
if *c != 0 {
break;
}
println!("{}", *c);
}
}
fn main() {
let v = vec![0; 10];
let mut itr = v.iter();
while let Some(c) = itr.next() {
foo(&mut itr);
}
}
Instead of generics, we can also use a trait object:
fn foo<'a>(itr: &mut Iterator<Item=&'a i32>) {
while let Some(c) = itr.next() {
if *c != 0 {
break;
}
println!("{}", *c);
}
}
fn main() {
let v = vec![0; 10];
let mut itr = v.iter();
while let Some(c) = itr.next() {
foo(&mut itr);
}
}
The chapter on trait objects from the Rust book explains the difference between these solutions.
The solution was to add
use std::slice::Iter;
and the type was
fun foo<'a>(itr : &mut Iter<'a, i32>) {}