oxipng throwing RuntimeError: unreachable when called - rust

I'm trying to create a small WASM project for image compression.
After some search in github, I noticed that oxipng 2.2.2 has a target for wasm32-unknown-unknown, hence why I'm using that.
I'm using wasm-pack for creating the wasm file + JS bindings with target -t web
This is the code:
extern crate oxipng;
mod utils;
use std::error::Error;
use wasm_bindgen::prelude::*;
use oxipng::*;
#[wasm_bindgen]
extern "C" {
// Use `js_namespace` here to bind `console.log(..)` instead of just
// `log(..)`
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
// Next let's define a macro that's like `println!`, only it works for
// `console.log`. Note that `println!` doesn't actually work on the wasm target
// because the standard library currently just eats all output. To get
// `println!`-like behavior in your app you'll likely want a macro like this.
#[macro_export]
macro_rules! console_log {
// Note that this is using the `log` function imported above during
// `bare_bones`
($($t:tt)*) => (crate::log(&format_args!($($t)*).to_string()))
}
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
#[cfg(feature = "wee_alloc")]
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
pub fn compress(data: &[u8]) -> Vec<u8> {
console_log!("{}", data.len());
let opts = Options::from_preset(6);
console_log!("after options");
let res = match optimize_from_memory(data, &&opts) {
Ok(res) => Ok(res),
Err(err) => Err(err),
};
match &res {
Ok(_) => console_log!("Optimized"),
Err(err) => console_log!("Error: {}", err),
}
return res.unwrap();
}
I don't ever get an error message, the last log I have is "after options".
In a nutshell, I'm using a Flutter web application that gets a PNG file, converts it into a Uint8List, and I send it as an integer List to the JS bindings.
When called, the following error happens:
RuntimeError: unreachable
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[1019]:0x5c6be
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[414]:0x4cd37
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[619]:0x54c96
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[915]:0x5b4ba
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[986]:0x5c139
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[645]:0x55885
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[569]:0x5324b
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[594]:0x53ff1
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[2]:0x554f
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[84]:0x2cbf2
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[73]:0x2a501
at http://localhost:3000/pkg/rust_png_module_bg.wasm:wasm-function[563]:0x52eaa
at compress (http://localhost:3000/pkg/rust_png_module.js:49:14)
at compressImage (http://localhost:3000/packages/rust_wasm/ui/screens/home/home_page.dart.lib.js:568:72)
at compressImage.next (<anonymous>)
at http://localhost:3000/dart_sdk.js:38640:33
at _RootZone.runUnary (http://localhost:3000/dart_sdk.js:38511:59)
at _FutureListener.thenAwait.handleValue (http://localhost:3000/dart_sdk.js:33713:29)
at handleValueCallback (http://localhost:3000/dart_sdk.js:34265:49)
at Function._propagateToListeners (http://localhost:3000/dart_sdk.js:34303:17)
at _Future.new.[_completeWithValue] (http://localhost:3000/dart_sdk.js:34151:23)
at async._AsyncCallbackEntry.new.callback (http://localhost:3000/dart_sdk.js:34172:35)
at Object._microtaskLoop (http://localhost:3000/dart_sdk.js:38778:13)
at _startMicrotaskLoop (http://localhost:3000/dart_sdk.js:38784:13)
at http://localhost:3000/dart_sdk.js:34519:9
Since this version is old, I don't know if I should revert back to an older version of Rust
$ rustup --version
rustup 1.24.3 (ce5817a94 2021-05-31)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.55.0 (c8dfcfe04 2021-09-06)`
Thank you in advance

The problem is you're using a very old version of oxipng (v2.2.2) that didn't support wasm yet. I believe wasm support was added in v2.3.0 (link to issue that was fixed). Anyways, you should be able to use the latest version just fine with wasm, just make sure you disable the default features when adding the crate to your Cargo.toml:
[dependencies]
oxipng = { version = "5", default-features = false }

Related

Tests fail when renaming identifiers, etc

I've got a large repo in which I noticed that some tests started failing after I added a dependency to Cargo.toml, despite the dependency never being referenced. I began to investigate, and was able to reproduce the problem consistently in this repo. I'll reproduce the code of the main file here:
mod test {
pub fn b<T>(db: *mut libsqlite3_sys::sqlite3, _: T) {
let rc = unsafe {
libsqlite3_sys::sqlite3_create_function(
db, // db
"x".as_ptr() as _, // zFunction
0, // nArg
0, // eTextRep
std::ptr::null_mut(), // pApp
None, // xFunc
None, // xStep
None, // xFinal
)
};
match rc {
libsqlite3_sys::SQLITE_MISUSE => (),
x => panic!("Wanted SQLITE_MISUSE, got {:?}", x),
}
}
}
#[test]
#[ignore]
fn z() {
format!("{:?}", &[1, 2, 3, 4]);
panic!("not run");
}
#[test]
fn a() {
const FILENAME: &[u8] = b":memory:\0";
let mut db: *mut libsqlite3_sys::sqlite3 = std::ptr::null_mut();
let rc = unsafe { libsqlite3_sys::sqlite3_open(FILENAME.as_ptr() as _, &mut db) };
assert_eq!(rc, libsqlite3_sys::SQLITE_OK);
test::b(db, 0);
}
On my computer, these tests pass, meaning that sqlite3_create_function is returning SQLITE_MISUSE.
$ cargo test --lib --features=static
Finished test [unoptimized + debuginfo] target(s) in 0.52s
Running unittests src/lib.rs (target/debug/deps/sqlite3_ext-5449511dde1f34ef)
running 2 tests
test z ... ignored
test a ... ok
test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.01s
Now, it shouldn't be returning MISUSE, because as far as I can tell everything about this code is valid. However, here's where it gets weird:
If I don't use --features=static, the test fails. Note that nothing references this feature whatsoever.
If I remove the format! line, the test fails. Note that the code is never called.
If I add or remove any dependencies to Cargo.toml, the test fails. None of the changes are referenced anywhere in the code.
If I rename the feature "static" to anything else, the test fails.
If I rename the module "test" to anything else, the test fails.
If I run this code on Linux, the test fails.
I am able to add [features] joke = [] to Cargo.toml, and then I get this behavior:
cargo test --lib --features=joke fails (no MISUSE)
cargo test --lib --features=static passes (MISUSE)
cargo test --lib --features=static,joke fails (no MISUSE)
I am at my wit's end. I am running macOS 10.14.6 (18G9323), rustc 1.61.0 (fe5b13d68 2022-05-18). Any help would be greatly appreciated. I've also uploaded binaries to GitHub for investigation if it helps.
Thanks to #thomcc who responded on the rusqlite Discord:
you’re not passing a nul-terminated string to c for one
This was the issue. In most cases the only problem this caused was that my application-defined function was never removed, but in this particular case it resulted in an SQLITE_MISUSE being returned. Properly converting my &str to CString resolves the issue.

Rust playground - provide command line argument

I am using the Rust Playground to test a piece of code, sample:
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
let query = args.get(1).unwrap();
// do something ...
}
Playground link
How do I provide a command-line argument for running a program in Rust Playground? The sample drop-down next to the run button does not have any link or perhaps I am missing it?
Thanks!
You can't, there is an open issue for this feature
As #Stargateur correctly answered, it's currently impossible to provide input for the playground code itself. However, there's a little trick which can work in relatively simple cases: we can execute std::process::Command, which starts bash, which can execute arbitrary code - including cargo.
Here's how it can look like, for example:
// This is your real `fn main`, which would use the input.
// It can contain everything that's usually possible in the playground.
#[cfg(real_main)]
fn main() {
let args: Vec<String> = std::env::args().collect();
println!("Args: {:?}", args);
}
// This is the wrapper-function, directly executed by the playground.
#[cfg(not(real_main))]
fn main() {
// We're shelling out to `bash`, to execute `cargo run` with additional config.
let _ = std::process::Command::new("/bin/bash")
.args(&[
"-c",
concat!(
r##"{
"##,
// In case we have any kind of error, we want to exit loudly.
r##"
set -euo pipefail
"##,
// `cargo rustc` allows one to pass additional compiler flags.
// It's important that this will recompile the current crate only,
// since, if we had to build the whole dependency tree
// (which is quite large), playground will inevitably timeout.
r##"
cargo rustc -q -- --cfg real_main
"##,
// When building in release mode, replace `target/debug`
// with `target/release`.
r##"
./target/debug/playground arg1 arg2 arg3
"##,
// Finally, we rediirect the stderr of the whole script to stdout,
// to show it in the playground output.
r##"
} 2>&1"##
),
])
// On running `Command::status`, output is piped by default,
// so it will be shown as usual.
.status();
}
Playground link

Why do I get the error "there is no reactor running, must be called from the context of Tokio runtime" even though I have #[tokio::main]?

I'm following the mdns Rust documentation and pasted the example code but it throws the following error:
thread 'main' panicked at 'there is no reactor running, must be called from the context of Tokio runtime'
Here's the code that I have:
use futures_util::{pin_mut, stream::StreamExt};
use mdns::{Error, Record, RecordKind};
use std::{net::IpAddr, time::Duration};
const SERVICE_NAME: &'static str = "_googlecast._tcp.local";
#[tokio::main]
async fn main() -> Result<(), Error> {
// Iterate through responses from each Cast device, asking for new devices every 15s
let stream = mdns::discover::all(SERVICE_NAME, Duration::from_secs(15))?.listen();
pin_mut!(stream);
while let Some(Ok(response)) = stream.next().await {
let addr = response.records().filter_map(self::to_ip_addr).next();
if let Some(addr) = addr {
println!("found cast device at {}", addr);
} else {
println!("cast device does not advertise address");
}
}
Ok(())
}
fn to_ip_addr(record: &Record) -> Option<IpAddr> {
match record.kind {
RecordKind::A(addr) => Some(addr.into()),
RecordKind::AAAA(addr) => Some(addr.into()),
_ => None,
}
}
Dependencies:
[dependencies]
mdns = "1.1.0"
futures-util = "0.3.8"
tokio = { version = "0.3.3", features = ["full"] }
What am I missing? I tried looking online but haven't found how to create a reactor for this use case.
You are using a newer version of Tokio, such as 0.3 or 1.x, and many packages, including mdns 1.1.0, rely on an older version of Tokio, such as 0.2.
% cargo tree -d
tokio v0.2.22
└── mdns v1.1.0
└── example_project v0.1.0
tokio v0.3.3
└── example_project v0.1.0
For now, you will need to match versions of the Tokio runtime. The easiest way is to use Tokio 0.2 yourself. The tokio-compat-02 crate may also be useful in some cases.
See also:
Why is a trait not implemented for a type that clearly has it implemented?
Various error messages with the same root cause:
there is no reactor running, must be called from the context of a Tokio 1.x runtime
there is no reactor running, must be called from the context of Tokio runtime
not currently running on the Tokio runtime
Fix for me was adding this to Cargo.toml:
[dependencies]
async-std = { version = "1", features = ["attributes", "tokio1"] }
https://github.com/ATiltedTree/ytextract/issues/25
At the time of writing, a fair amount of crates are already using Tokio v1, but others might still be under an experimental phase. Check your crates for prerelease versions which might have already upgraded their tokio runtime compatibility.
A relevant example of this was actix-web, which uses runtime 1.0 of Tokio since version 4. Although there were prereleases of this major increment since 2022-01-07, version 4.0.0 was only released in 2022-02-25.
actix-web = { version = "4.0.0-beta.10" }

Serving static files with actix-web 2.0

I'm struggling with actix-web 2.0 framework of rust. I want my rust server to serve the my index.html file but most of the help available is of older versions and hence a lot has changed in newer version. I tried following code but it's not working for actix-web 2.0. Please suggest some working solution in actix-web 2.0.
use actix_files::NamedFile;
use actix_web::{HttpRequest, Result};
async fn index(req: HttpRequest) -> Result<NamedFile> {
Ok(NamedFile::open(path_to_file)?)
}
By trying the code given in the answer I could serve a single html file but it is unable to load the linked JavaScript file. I have tried the following approach suggested in https://actix.rs/docs/static-files/ to serve the directory.
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
dotenv::dotenv().ok();
std::env::set_var("RUST_LOG", "actix_web=debug");
let database_url = std::env::var("DATABASE_URL").expect("set DATABASE_URL");
// create db connection pool
let manager = ConnectionManager::<PgConnection>::new(database_url);
let pool: Pool = r2d2::Pool::builder()
.build(manager)
.expect("Failed to create pool.");
//Serving the Registration and sign-in page
async fn index(_req: HttpRequest) -> Result<NamedFile> {
let path: PathBuf = "./static/index.html".parse().unwrap();
Ok(NamedFile::open(path)?)
}
// Start http server
HttpServer::new(move || {
App::new()
.data(pool.clone())
.service(fs::Files::new("/static", ".").show_files_listing())
.route("/", web::get().to(index))
.route("/users", web::get().to(handler::get_users))
.route("/users/{id}", web::get().to(handler::get_user_by_id))
.route("/users", web::post().to(handler::add_user))
.route("/users/{id}", web::delete().to(handler::delete_user))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Above is my main method. In browser console I'm still getting the error that unable to load the Registration.js resource. Following is my folder structure:
-migrations
-src
-main.rs
-handler.rs
-errors.rs
-models.rs
-schema.rs
-static
-index.html
-Registration.js
-target
Cargo.toml
.env
Cargo.lock
diesel.toml
I have already built the backend with DB integration and it is working fine as checked by curl commands and now I'm trying to build front end and as first step trying to serve static files.
I am not sure what problem you're facing since the description is not detailed, however, I ran the default example and it is working.
use actix_files::NamedFile;
use actix_web::{HttpRequest, Result};
use std::path::PathBuf;
/// https://actix.rs/docs/static-files/
async fn index(_req: HttpRequest) -> Result<NamedFile> {
let path: PathBuf = "./files/index.html".parse().unwrap();
Ok(NamedFile::open(path)?)
}
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
use actix_web::{web, App, HttpServer};
HttpServer::new(|| App::new().route("/", web::get().to(index)))
.bind("127.0.0.1:8088")?
.run()
.await
}
project structure
- files/index.html
- src/index.rs
- cargo.toml
dependencies
[dependencies]
actix-web = "2.0.0"
actix-files = "0.2.2"
actix-rt = "1.1.1"
If you want to really embed resources into executable you can use https://crates.io/crates/actix-web-static-files.
It uses build.rs to prepare resources and later you can just have single executable without dependencies.
As extra it support npm based builds out of the box.
Basically I am an author of this crate. There are versions both for 2.x and 3.x versions of actix-web.
Please see the below code that it works for the whole subdirectories:
main.rs
use actix_files as fs;
use actix_web::{App, HttpServer};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().service(
fs::Files::new("/", "./public")
.show_files_listing()
.index_file("index.html")
.use_last_modified(true),
)
})
.bind("0.0.0.0:8000")?
.run()
.await
}
Cargo.toml
[package]
name = "actixminimal"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "4"
actix-files = "0.6.2"
It perform file serving very fast ever I'd tried.
In this case, you can create a "public" or you can use your own "static" folder (then change your code related to the folder name) or you can export the static files from your web framework. I use GatsbyJS and I use deploy parameter to "public" folder.
I share it on my github.
https://github.com/openmymai/actixminimal.git

"could not rename crate" when compiling a basic example of rustless on Windows

I'm trying to build rustless on Windows:
This is my Cargo.toml:
[dependencies.rustless]
git = "https://github.com/rustless/rustless"
[package]
name = "ccampo_substancias_srv"
version = "0.0.1"
authors = [ "------------------------------" ]
[[bin]]
name = "Rest_test"
This is main.rs:
#![feature(plugin)]
#[plugin]
extern crate rustless;
extern crate hyper;
extern crate iron;
extern crate "rustc-serialize" as rustc_serialize;
extern crate valico;
use hyper::status::StatusCode;
use iron::Iron;
use rustless::{
Application, Api, Nesting, Versioning
};
use rustc_serialize::json::ToJson;
fn main() {
let api = Api::build(dsl!(|api| {
// Specify API version
version("v1", Versioning::AcceptHeader("chat"));
prefix("api");
// Create API for chats
mount(Api::build(dsl!(|chats_api| {
after(|client, _params| {
client.set_status(StatusCode::NotFound);
Ok(())
});
// Add namespace
namespace("chats/:id", dsl!(|chat_ns| {
// Valico settings for this namespace
params(|params| {
params.req_typed("id", valico::u64())
});
// Create endpoint for POST /chats/:id/users/:user_id
post("users/:user_id", dsl!(|endpoint| {
// Add description
desc("Update user");
// Valico settings for endpoint params
params(|params| {
params.req_typed("user_id", valico::u64());
params.req_typed("name", valico::string())
});
handle(|client, params| {
client.json(&params.to_json())
})
}));
}));
})));
}));
let app = Application::new(api);
Iron::new(app).listen("localhost:4000").unwrap();
println!("On 4000");
println!("Rustless server started!");
}
Building with "cargo build --verbose" and rust 1.5 (64bit) on Windows 10.
This is the error I'm getting, looks like it's related to some file path:
Fresh jsonway v0.3.5
Fresh conduit-mime-types v0.7.3
Fresh winapi v0.2.5
Build failed, waiting for other jobs to finish...
could not rename crate "C:\\Users\\Pedro\\workspace\\ccampo-substancias-srv\\target\\debug\\build\\advapi32-sys-cfef7a1f30f1e5f6\\build_script_build.exe"
Caused by: Acesso negado. (os error 5)
Do you have antivirus/anti-malware software on your computer? It might be trying to analyze your program, locking the file. Try disabling it temporarily or adding an exception on your project directory, then try building again.

Resources