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.
Related
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.
In this code snippet
protocol MyProtocol {}
extension Int: MyProtocol {}
let a: Array<MyProtocol> = Array<Int>()
let b: ArraySlice<MyProtocol> = a[...]
let c: Array<Int> = a as! Array<Int>
let d: ArraySlice<Int> = b as! ArraySlice<Int>
d warns with Cast from 'ArraySlice<MyProtocol>' to unrelated type 'ArraySlice<Int>' always fails.
Why can't a Slice be cast in the same way as the original Array? Can this snippet be modified to give the Array casting behaviour to the Slice?
This is basically due to how generic variance in Swift works.
Only few types are variant in Swift, including Array<T> and Set<T>. Most other types, and the types you define, are invariant.
Invariance means that T<A> and T<B> are unrelated types even if A and B are related.
Array<T> and Set<T> are covariant, which means that a Array<A> can be assigned to a variable of type Array<B> if A is a subtype of B. You can force it to go the other way (like you did in the third line) by using as!.
ArraySlice<T>, like many other types, is simply invariant. You need to do this to convert:
let d: ArraySlice<Int> = ArraySlice(b.map { $0 as! Int })
As an addendum answer to the correct answer by #Sweeper for people who are looking for type-flexible performant copy-by-ref arrays, I ended up rolling a solution which wraps an array in a class and exposes some of the API for an array.
Not a great solution, but it does what I need it to. Boo Apple for not keeping their APIs for this sort of thing consistent.
class ArrayReference<T>: Collection {
private(set) var array : Array<T>
init(_ encapsulating: Array<T>? = nil) {
self.array = encapsulating ?? []
}
var startIndex: Int {
get {
return array.startIndex
}
}
var endIndex: Int {
get {
return array.endIndex
}
}
var count : Int {
get {
return array.count
}
}
func index(after i: Int) -> Int {
return array.index(after: i)
}
subscript (index: Int) -> T {
get { return array[index] }
set(newValue) { array[index] = newValue }
}
func append(_ newValue: T) {
array.append(newValue)
}
func removeAll() {
array.removeAll()
}
var first: T? {
if array.count > 0 {
return array[0]
} else {
return nil
}
}
var last: T? {
if array.count > 0 {
return array[array.count - 1]
} else {
return nil
}
}
func asType<C>(_ type: C.Type) -> ArrayReference<C>? {
if let array = self.array as? Array<C> {
return ArrayReference<C>(array)
} else {
return nil
}
}
}
extension ArrayReference: Equatable where T: Equatable {
static func == (lhs: ArrayReference<T>, rhs: ArrayReference<T>) -> Bool {
if lhs.count == rhs.count {
var equal = true
for (lhs, rhs) in zip(lhs, rhs) {
equal = equal && (lhs == rhs)
}
return equal
} else {
return false
}
}
}
I'm trying to create an extension but somehow it keeps saying:
Ambiguous reference to member '=='.
class Foo: Equatable {
var string = ""
var number = 0
init(string: String, number: Int) {
self.string = string
self.number = number
}
}
extension Array where Iterator.Element: Foo {
mutating func replace(object: Foo) {
if let index = index(where: { $0.number == object.number}) {
self[index] = object
}
}
}
func ==(lhs: Foo, rhs: Foo) -> Bool {
return lhs.number == rhs.number
}
What am I doing wrong?
Try this:
extension Array where Element: Foo {
mutating func replace(object: Element) {
if let index = index(where: {$0.number == object.number}) {
self[index] = object
}
}
}
To make self[index] = object valid, object needs to be an Element of the Array, which can be any subclass of Foo.
And unfortunately, Swift cannot infer the type of Element from the constraint to Iterator.Element. You may need to declare the constraint to Element directly.
(And to test the code above, I have removed : Equatable from your Foo, which is irrelevant when you use index(where:) in the extension.)
Swift 5 version and support multiple object replacement(add if not exist).
extension Foo {
public static func == (lhs: Object, rhs: Object) -> Bool {
return lhs.id == rhs.id
}
}
extension Array where Element: Foo {
mutating func replace(object: Element) -> Bool {
if let index = firstIndex(where: {$0 == object}) {
self[index] = object
return true
}
return false
}
mutating func replace(objects: Array<Element>) {
objects.forEach { (object) in
if replace(object: object) == false {
self.append(object)
}
}
}
}
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>) {}
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.