Incorrect initial capacity for ArrayList - zig

I've been going through ziglearn and have made my way to ArrayList. I understand the example given there but when I try something a bit more complex I run into errors. Based on the error it seems like my array doesn't have valid memory when it goes to append the new element, but I've set the initial capacity to 10. What am I doing wrong?
const std = #import("std");
const page_allocator = std.heap.page_allocator;
const Allocator = std.mem.Allocator;
const C = struct {
list: std.ArrayList(A),
pub fn init(allocator: Allocator) !*C {
var a = try std.ArrayList(A).initCapacity(allocator, 10);
return &C{ .list = a };
}
pub fn info(self: *C) void {
std.log.info("len {} cap {}", .{ self.list.items.len, self.list.capacity });
}
pub fn addElement(self: *C, a: A) !*C {
try self.list.append(a);
return self;
}
};
const A = struct { e: []const u8 };
test "with arraylist" {
var foo = try C.init(page_allocator);
foo.info();
_ = try foo.addElement(.{ .e = "bar" });
}
Can see below the initial capacity is not 10, it changes with each run pointing to its uninitialized. Am I missing a step to initialize memory for the ArrayList?
[default] (info): len 0 cap 140728248984328
Segmentation fault at address 0x0
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/mem/Allocator.zig:159:30: 0x219c3c in reallocAdvancedWithRetAddr__anon_4653 (test)
return self.vtable.resize(self.ptr, buf, buf_align, new_len, len_align, ret_addr);
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/mem/Allocator.zig:356:43: 0x216faf in reallocAtLeast__anon_3534 (test)
return self.reallocAdvancedWithRetAddr(old_mem, old_alignment, new_n, .at_least, #returnAddress());
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/array_list.zig:353:89: 0x215697 in ensureTotalCapacityPrecise (test)
const new_memory = try self.allocator.reallocAtLeast(self.allocatedSlice(), new_capacity);
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/array_list.zig:338:55: 0x2170f6 in ensureTotalCapacity (test)
return self.ensureTotalCapacityPrecise(better_capacity);
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/array_list.zig:377:41: 0x21577c in addOne (test)
try self.ensureTotalCapacity(newlen);
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/array_list.zig:167:49: 0x213c16 in append (test)
const new_item_ptr = try self.addOne();
^
src/main.zig:154:29: 0x213b86 in addElement (test)
try self.list.append(a);
^
src/main.zig:165:27: 0x213ce7 in test.with arraylist (test)
_ = try foo.addElement(.{ .e = "bar" });
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/test_runner.zig:63:28: 0x2164f0 in main (test)
} else test_fn.func();
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/start.zig:596:22: 0x21463b in posixCallMainAndExit (test)
root.main();
^
/home/john/zig/zig-linux-x86_64-0.10.0/lib/std/start.zig:368:5: 0x214101 in _start (test)
#call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
^

Your C.init function returns a pointer to C which is on the stack of the init function. This pointer becomes invalid as soon as the function exits.
Just don't return it as a pointer:
pub fn init(allocator: Allocator) !C {
var a = try std.ArrayList(A).initCapacity(allocator, 10);
return C{ .list = a };
}
Or, alternatively, you could put C into the allocator's memory:
pub fn init(allocator: Allocator) !*C {
var result = try allocator.create(C);
result.list = try std.ArrayList(A).initCapacity(allocator, 10);
return result;
}
But avoid doing this unless you have a good reason, as it limits what you can do with C.

Related

Current Way to Get User Input in Zig

I'm following this blog post on 'comptime' in Zig.
The following line no longer compiles in Zig 0.6.0.
const user_input = try io.readLineSlice(buf[0..]);
Below is the full function:
fn ask_user() !i64 {
var buf: [10]u8 = undefined;
std.debug.warn("A number please: ");
const user_input = try io.readLineSlice(buf[0..]);
return fmt.parseInt(i64, user_input, 10);
}
What is the equivalent in the current version (of getting user input)?
You can use the method readUntilDelimiterOrEof of stdin instead:
const stdin = std.io.getStdIn().reader();
pub fn readUntilDelimiterOrEof(self: #TypeOf(stdin), buf: []u8, delimiter: u8) !?[]u8
So, the code can be:
fn ask_user() !i64 {
const stdin = std.io.getStdIn().reader();
const stdout = std.io.getStdOut().writer();
var buf: [10]u8 = undefined;
try stdout.print("A number please: ", .{});
if (try stdin.readUntilDelimiterOrEof(buf[0..], '\n')) |user_input| {
return std.fmt.parseInt(i64, user_input, 10);
} else {
return #as(i64, 0);
}
}
See also: Zig 0.7.0 documentation.

Basic parsing Flow with Babel not working

I cannot seem to be able to parse Flow using Babel, its not recognising types or "declare" and is coming up with errors on them :-
const fs = require("fs");
const babel = require("#babel/core");
const parser = require('#babel/parser');
const generate = require('#babel/generator').default;
if (process.argv.length == 3) {
const filename = process.argv[2];
const sourceCode = fs.readFileSync(filename).toString();
console.log("sourceCode = ", sourceCode);
var options = {
"sourceType": "module", // parse in strict mode and allow module declarations
"presets": ["#babel/preset-flow"]
};
const parsedAst = parser.parse(sourceCode, options);
console.log("parsedAst = ", parsedAst)
const { codeOutput, map, ast } = babel.transformFromAstSync(parsedAst, sourceCode, { ast: true } );
console.log("ast = ", JSON.stringify(ast, 2, 2))
const output = generate(ast, { /* options */ }, sourceCode);
console.log("codeOutput = ", codeOutput);
console.log("output = ", output);
};
given the following code :-
// #flow strict
const MAX_SUGGESTIONS = 5;
/**
* Given [ A, B, C ] return ' Did you mean A, B, or C?'.
*/
declare function didYouMean(suggestions: $ReadOnlyArray<string>): string;
// eslint-disable-next-line no-redeclare
declare function didYouMean(
subMessage: string,
suggestions: $ReadOnlyArray<string>,
): string;
// eslint-disable-next-line no-redeclare
export default function didYouMean(firstArg, secondArg?) { ... }
I am getting errors on declare also on types :-
C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:730
throw err;
^
SyntaxError: Unexpected token, expected ";" (8:8)
at Parser._raise (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:723:17)
at Parser.raiseWithData (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:716:17)
at Parser.raise (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:710:17)
at Parser.unexpected (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:8610:16)
at Parser.semicolon (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:8592:40)
at Parser.parseExpressionStatement (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:11449:10)
at Parser.parseStatementContent (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:11050:19)
at Parser.parseStatement (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:10916:17)
at Parser.parseBlockOrModuleBlockBody (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:11490:25)
at Parser.parseBlockBody (C:\Users\aaron\Tests\Babel\generator-test\node_modules\#babel\parser\lib\index.js:11477:10) {
loc: Position { line: 8, column: 8 },
pos: 118
}
Github :-
https://github.com/AaronNGray/babel-flow-parser-test
Tag v0 is without package-lock.json
Need to add some extra details which I cannot think of ???
The following works :-
const fs = require('fs');
const babel = require('#babel/core');
if (process.argv.length == 3) {
const filename = process.argv[2];
const source = fs.readFileSync(filename).toString();
const ast = babel.parseSync(source, {
babelrc: false,
configFile: false,
ast: true,
parserOpts: {
plugins: ['flow', 'jsx'],
},
filename,
});
console.log("ast = ", JSON.stringify(ast, null, 2))
}
I would still like to know if the original will work with modification as its the near enough what is specified in the Babel documentation.

How do I extract messages from an unbounded queue every N seconds and spawn them on to a Tokio handler?

I am trying to extract messages (which are futures themselves) from an unbounded queue every N seconds and spawn them into the Tokio handler.
I’ve tried dozens of variations but I cannot seem to find the right approach. It looks like it should be possible, but I always hit a future type mismatch or end up with borrow issues.
This is the code that shows more or less what I want:
let fut = Interval::new_interval(Duration::from_secs(1))
.for_each(|num| vantage_dequeuer.into_future() )
.for_each(|message:VantageMessage |{
handle.spawn(message);
return Ok(());
})
.map_err(|e| panic!("delay errored; err={:?}", e));
core.run(fut);
Complete code:
extern crate futures; // 0.1.24
extern crate tokio; // 0.1.8
extern crate tokio_core; // 0.1.17
use futures::future::ok;
use futures::sync::mpsc;
use futures::{Future, Stream};
use std::thread;
use std::time::Duration;
use tokio::timer::Interval;
use tokio_core::reactor::Core;
type VantageMessage = Box<Future<Item = (), Error = ()> + Send>;
fn main() {
let (enqueuer, dequeuer) = mpsc::unbounded();
let new_fut: VantageMessage = Box::new(ok(()).and_then(|_| {
println!("Message!");
return Ok(());
}));
enqueuer.unbounded_send(new_fut);
let joinHandle = worker(Some(dequeuer));
joinHandle.join();
}
/*
Every second extract one message from dequeuer (or wait if not available)
and spawn it in the core
*/
fn worker(
mut vantage_dequeuer: Option<mpsc::UnboundedReceiver<VantageMessage>>,
) -> thread::JoinHandle<()> {
let dequeuer = dequeuer.take().unwrap();
let joinHandle = thread::spawn(|| {
let mut core = Core::new().unwrap();
let handle = core.handle();
let fut = Interval::new_interval(Duration::from_secs(1))
.for_each(|num| vantage_dequeuer.into_future())
.for_each(|message: VantageMessage| {
handle.spawn(message);
return Ok(());
})
.map_err(|e| panic!("delay errored; err={:?}", e));
core.run(fut);
println!("Returned!");
});
return joinHandle;
}
Playground
error[E0425]: cannot find value `dequeuer` in this scope
--> src/main.rs:33:20
|
33 | let dequeuer = dequeuer.take().unwrap();
| ^^^^^^^^ not found in this scope
error[E0599]: no method named `into_future` found for type `std::option::Option<futures::sync::mpsc::UnboundedReceiver<std::boxed::Box<(dyn futures::Future<Item=(), Error=()> + std::marker::Send + 'static)>>>` in the current scope
--> src/main.rs:38:46
|
38 | .for_each(|num| vantage_dequeuer.into_future())
| ^^^^^^^^^^^
|
= note: the method `into_future` exists but the following trait bounds were not satisfied:
`&mut std::option::Option<futures::sync::mpsc::UnboundedReceiver<std::boxed::Box<(dyn futures::Future<Item=(), Error=()> + std::marker::Send + 'static)>>> : futures::Stream`
Interval and UnboundedReceiver are both streams, so I'd use Stream::zip to combine them:
The zipped stream waits for both streams to produce an item, and then returns that pair. If an error happens, then that error will be returned immediately. If either stream ends then the zipped stream will also end.
extern crate futures; // 0.1.24
extern crate tokio; // 0.1.8
extern crate tokio_core; // 0.1.17
use futures::{
future::ok,
sync::mpsc,
{Future, Stream},
};
use std::{thread, time::Duration};
use tokio::timer::Interval;
use tokio_core::reactor::Core;
type VantageMessage = Box<Future<Item = (), Error = ()> + Send>;
pub fn main() {
let (tx, rx) = mpsc::unbounded();
let new_fut: VantageMessage = Box::new(ok(()).and_then(|_| {
println!("Message!");
Ok(())
}));
tx.unbounded_send(new_fut).expect("Unable to send");
drop(tx); // Close the sending side
worker(rx).join().expect("Thread had a panic");
}
fn worker(queue: mpsc::UnboundedReceiver<VantageMessage>) -> thread::JoinHandle<()> {
thread::spawn(|| {
let mut core = Core::new().unwrap();
let handle = core.handle();
core.run({
Interval::new_interval(Duration::from_secs(1))
.map_err(|e| panic!("delay errored; err={}", e))
.zip(queue)
.for_each(|(_, message)| {
handle.spawn(message);
Ok(())
})
})
.expect("Unable to run reactor");
println!("Returned!");
})
}
Note that this doesn't actually wait for any of the spawned futures to complete before the reactor shuts down. If you want that, I'd switch to tokio::run and tokio::spawn:
fn worker(queue: mpsc::UnboundedReceiver<VantageMessage>) -> thread::JoinHandle<()> {
thread::spawn(|| {
tokio::run({
Interval::new_interval(Duration::from_secs(1))
.map_err(|e| panic!("delay errored; err={}", e))
.zip(queue)
.for_each(|(_, message)| {
tokio::spawn(message);
Ok(())
})
});
println!("Returned!");
})
}

Handling streaming iterator as normal iterator by using PhantomData and unsafe

I know the code below is hacky, but could it be called safe and idiomatic Rust? Is there better way for this?
// needs to do 'rustup default nightly' to run under valgrind
// #![feature(alloc_system, global_allocator, allocator_api)]
// extern crate alloc_system;
// use alloc_system::System;
// #[global_allocator]
// static A: System = System;
struct Foo<'a> {
v: Vec<u8>,
pos: usize,
phantom: std::marker::PhantomData<&'a u8>,
}
impl<'a> Iterator for Foo<'a> {
type Item = &'a mut u8;
fn next(&mut self) -> Option<&'a mut u8> {
let r = self.v.get_mut(self.pos);
if r.is_some() {
self.pos += 1;
unsafe { Some(&mut *(r.unwrap() as *mut u8)) }
} else {
None
}
}
}
impl<'a> Foo<'a> {
fn reset(&mut self) {
self.pos = 0;
}
}
fn main() {
let mut x = Foo {
v: (1..10).collect(),
pos: 0,
phantom: std::marker::PhantomData,
};
let vp = x.v.as_ptr();
{
for i in &mut x {
println!("{}", i);
}
}
{
x.reset();
}
{
for i in &mut x {
*i *= *i;
}
}
{
x.reset();
}
{
for i in &mut x {
println!("{}", i);
}
}
assert!(vp == x.v.as_ptr());
}
Write a little bit in the comment, Valgrind told me no leak and the result is as expected under Rust 1.26.0-nightly and 1.25.0.
Related:
How do I write an iterator that returns references to itself?
Iterator returning items by reference, lifetime issue
This code is not safe. The user of the type may choose any lifetime, including 'static:
fn constructor() -> Foo<'static> {
Foo {
v: vec![42; 10],
pos: 0,
phantom: std::marker::PhantomData,
}
}
fn example() -> &'static u8 {
let mut f = constructor();
f.next().unwrap()
}
fn main() {
println!("example: {}", example());
}
Here, example returns a reference to a variable that is no longer in scope, accessing invalid memory and subverting the restrictions you must uphold.
There's an example of how you could write this code with no unsafe whatsoever in another Q&A.

Make function declared in a closure global without using window

How do I make a function declared in a closure, global ? This is for a google apps script, hence no window.
There is documentation on how to use closures in google apps scripts, but the example declares an object instead of a function.
http://code.google.com/googleapps/appsscript/articles/appengine.html
var JSON = JSON || {};
// foo = function(){}
(function ()
{
...
foo = function (a, b)
{
...
}
foo.prototype =
{
...
}
// window.foo = foo; // Not Possible
}());
This should work:
var globalFoo;
(function ()
{
...
foo = function (a, b)
{
...
}
foo.prototype =
{
...
}
globalFoo = foo;
// window.foo = foo; // Not Possible
}());
I've made a test in a regular html running on the browser and is works fine. Here is the example:
var globalFoo;
console.log("O1")
console.log(globalFoo);
(function(){
console.log("I1")
console.log(globalFoo);
var x = 13;
var foo = function() {
console.log('foo caled ' + x);
x++;
return true;
}
foo();
globalFoo = foo;
console.log("I2")
console.log(globalFoo);
})();
console.log("O1")
console.log(globalFoo);
console.log(globalFoo());
The firebug output to that is:
O1
undefined
I1
undefined
foo caled 13
I2
function()
O1
function()
foo caled 14
true

Resources