锘??xml version="1.0" encoding="utf-8" standalone="yes"?>精品综合久久久久久98,AV无码久久久久不卡网站下载,韩国三级大全久久网站http://www.shnenglu.com/jinq0123/category/21420.htmlzh-cnWed, 05 Oct 2022 13:26:52 GMTWed, 05 Oct 2022 13:26:52 GMT60Implementation of user data in cursive::Cursivehttp://www.shnenglu.com/jinq0123/archive/2022/10/02/229436.html閲戝簡閲戝簡Sun, 02 Oct 2022 08:38:00 GMThttp://www.shnenglu.com/jinq0123/archive/2022/10/02/229436.htmlhttp://www.shnenglu.com/jinq0123/comments/229436.htmlhttp://www.shnenglu.com/jinq0123/archive/2022/10/02/229436.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/229436.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/229436.htmlImplementation of user data in cursive::Cursive

(Jin Qing's Column, Oct., 2022)

cursive::Cursive can store any user data:

pub struct Cursive { ... // User-provided data. user_data: Box<dyn Any>, } impl Cursive { ... pub fn set_user_data<T: Any>(&mut self, user_data: T) { self.user_data = Box::new(user_data); } pub fn user_data<T: Any>(&mut self) -> Option<&mut T> { self.user_data.downcast_mut() } pub fn take_user_data<T: Any>(&mut self) -> Option<T> { ... } pub fn with_user_data<F, T, R>(&mut self, f: F) -> Option<R> where F: FnOnce(&mut T) -> R, T: Any, { self.user_data().map(f) }

Example:

let mut siv = cursive_core::Cursive::new(); // Start with a simple `Vec<i32>` as user data. siv.set_user_data(vec![1i32, 2, 3]); assert_eq!(siv.user_data::<Vec<i32>>(), Some(&mut vec![1i32, 2, 3])); // Let's mutate the data a bit. siv.with_user_data(|numbers: &mut Vec<i32>| numbers.push(4)); // If mutable reference is not enough, we can take the data by value. let data: Vec<i32> = siv.take_user_data().unwrap(); assert_eq!(data, vec![1i32, 2, 3, 4]); // At this point the user data was removed and is no longer available. assert_eq!(siv.user_data::<Vec<i32>>(), None);


閲戝簡 2022-10-02 16:38 鍙戣〃璇勮
]]>
Rust sometimes needs manual type annotationhttp://www.shnenglu.com/jinq0123/archive/2022/04/29/229301.html閲戝簡閲戝簡Fri, 29 Apr 2022 02:14:00 GMThttp://www.shnenglu.com/jinq0123/archive/2022/04/29/229301.htmlhttp://www.shnenglu.com/jinq0123/comments/229301.htmlhttp://www.shnenglu.com/jinq0123/archive/2022/04/29/229301.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/229301.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/229301.htmlRust sometimes needs manual type annotation

(Jin Qing's Column, Apr., 2022)

This code compiles error:

      trait MyCallback: FnMut(&u32) -> () { }
impl<F: FnMut(&u32) -> ()> MyCallback for F { }
fn process_data(mut f: impl MyCallback) -> () {
    f(&0)
}
fn process_data_2(mut f: impl FnMut(&u32) -> ()) -> () {
    f(&0)
}
fn main() {
    // Doesn't compile
    process_data(|_| ());
    // Compiles
    process_data_2(|_| ());
}

    
      expected type `for<'r> FnMut<(&'r u32,)>`
              found type `FnMut<(&u32,)>`

    

Fix:

          process_data(|_: &_| ());

    

See: https://stackoverflow.com/questions/61671460/rust-type-mismatch-resolving-forr-with-closure-trait-alias-argument

Also see: https://github.com/rust-lang/rust/issues/58639

Sometimes, Rust needs a type annotation in closure.



閲戝簡 2022-04-29 10:14 鍙戣〃璇勮
]]>
How to work around rustup-init failurehttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229295.html閲戝簡閲戝簡Sun, 24 Apr 2022 06:09:00 GMThttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229295.htmlhttp://www.shnenglu.com/jinq0123/comments/229295.htmlhttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229295.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/229295.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/229295.htmlHow to work around rustup-init failure

(Jin Qing's Column, Mar., 2022)

rustup-init.exe may fail if some anti-virus software is running with realtime protection.

The error message is like this after many retries:

error: could not rename component file from 'C:\.../rust/html' to 'C:\.../rust/html'

See: https://github.com/rust-lang/rustup/issues/1912

And it is not possible to stop the anti-virus for a corporate laptop.

There is a way to workaround this. Here are the steps:

  1. Run rustup-init until it begins to retry renaming
  2. Kill rustup-init when it is retrying
    • rustup will be installed before the failure
    • do not let rustup-init do the cleanup after the final failure
  3. Run rustup update to install all.
  4. Run rustup-init again to setup others.

rustup update will report that rustc was not found:

C:\Users\jinqing01>rustup update
info: syncing channel updates for 'stable-x86_64-pc-windows-msvc'
...
info: removing previous version of component 'rustc'
warning: during uninstall component rustc was not found
...
info: installing component 'rustc'
...  
info: checking for self-updates
  stable-x86_64-pc-windows-msvc updated - rustc 1.59.0 (9d1b2106e 2022-02-23) (from (rustc does not exist))
info: cleaning up downloads & tmp directories

Rerun rustup-init to setup the toolchain:

C:\Users\jinqing01>cargo --version
error: no override and no default toolchain set
C:\Users\jinqing01>d:
D:\>cd tool
D:\Tool>rustup-init.exe
Welcome to Rust!
This will download and install the official compiler for the Rust
programming language, and its package manager, Cargo.
...
Rust is installed now. Great!
Press the Enter key to continue.
D:\Tool>cargo --version
cargo 1.59.0 (49d8809dc 2022-02-10)



閲戝簡 2022-04-24 14:09 鍙戣〃璇勮
]]>
Closure as the function parameterhttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229294.html閲戝簡閲戝簡Sun, 24 Apr 2022 06:06:00 GMThttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229294.htmlhttp://www.shnenglu.com/jinq0123/comments/229294.htmlhttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229294.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/229294.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/229294.htmlClosure as the function parameter

(Jin Qing's Column, Mar., 2022)

It is best to let the function take a closure trait as the parameter instead of a function pointer.

      fn foo(f: fn()) {
    f()
}
fn main() {
    foo(|| println!("hello"));
    let a = 123;
    foo(move || println!("{}", a))
}

    

compiles error:

      error[E0308]: mismatched types
 --> src/main.rs:9:9
  |
9 |     foo(move || println!("{}", a))
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found closure
  |
  = note: expected fn pointer `fn()`
                found closure `[closure@src/main.rs:9:9: 9:34]`
note: closures can only be coerced to `fn` types if they do not capture any variables
 --> src/main.rs:9:32
  |
9 |     foo(move || println!("{}", a))
  |                                ^ `a` captured here
For more information about this error, try `rustc --explain E0308`.

    

https://doc.rust-lang.org/book/ch19-05-advanced-functions-and-closures.html

Function pointers implement all three of the closure traits (Fn, FnMut, and FnOnce), so you can always pass a function pointer as an argument for a function that expects a closure. It’s best to write functions using a generic type and one of the closure traits so your functions can accept either functions or closures.



閲戝簡 2022-04-24 14:06 鍙戣〃璇勮
]]>
Deadlock detection must not run as tokio taskhttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229293.html閲戝簡閲戝簡Sun, 24 Apr 2022 06:04:00 GMThttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229293.htmlhttp://www.shnenglu.com/jinq0123/comments/229293.htmlhttp://www.shnenglu.com/jinq0123/archive/2022/04/24/229293.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/229293.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/229293.htmldeadlock detection must not run as tokio task

(Jin Qing's Column, Feb., 2022)

parking_lot has an experimental feature: deadlock_detection.

See: https://amanieu.github.io/parking_lot/parking_lot/deadlock/index.html

use std::thread;
use std::time::Duration;
use parking_lot::deadlock;
// Create a background thread which checks for deadlocks every 10s
thread::spawn(move || {
loop {
thread::sleep(Duration::from_secs(10));
let deadlocks = deadlock::check_deadlock();
if deadlocks.is_empty() {
continue;
}
println!("{} deadlocks detected", deadlocks.len());
for (i, threads) in deadlocks.iter().enumerate() {
println!("Deadlock #{}", i);
for t in threads {
println!("Thread Id {:#?}", t.thread_id());
println!("{:#?}", t.backtrace());
}
}
}
});

The output is like this:

1 deadlocks detected
Deadlock #0
Thread Id 16072
0: 0x7ff985cb659d - backtrace::backtrace::dbghelp::trace
at d:\Users\jinqing\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.63\src\backtrace\dbghelp.rs:98
...
13: 0x7ff985ae92f3 - lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock,cgc::scene_template::SceneTemplate>::read<parking_lot::raw_rwlock::RawRwLock,cgc::scene_template::SceneTemplate>
at d:\Users\jinqing\.cargo\registry\src\github.com-1ecc6299db9ec823\lock_api-0.4.6\src\rwlock.rs:448
14: 0x7ff985aeadf3 - cgc::scene::SceneData::check_body_collide
at E:\gitlab\yserver\gc\src\scene.rs:99
...
81: 0x7ff9f29b7034 - BaseThreadInitThunk
82: 0x7ff9f2b02651 - RtlUserThreadStart

But the deadlock detection thread can not be changed to a tokio task, because if deadlock happens, all tasks may be blocked, including the deadlock detection, causing no deadlock error output.

In the following example, if the number of the deadlock tasks is larger than the thread number of tokio runtime, all tasks will be blocked.

use std::{thread, time::Duration};
use parking_lot::RwLock;
use tokio::time;
#[tokio::main]
async fn main() {
tokio::spawn(async move {
for i in 0..999999 {
println!("{}", i);
time::sleep(Duration::from_secs(1)).await;
}
});
const MAX: i32 = 100;
for _ in 0..MAX {
tokio::spawn(async move {
{
// DEADLOCK!
let a = RwLock::new(());
let _g1 = a.write();
let _g2 = a.write();
}
time::sleep(Duration::from_secs(9999)).await;
});
}
println!("Hello, world!");
thread::sleep(Duration::from_secs(10));
}

The output is:

0
Hello, world!
_

If no deadlock, or the number of deadlock tasks is small, the output should be:

0
Hello, world!
1
2
3
...



閲戝簡 2022-04-24 14:04 鍙戣〃璇勮
]]>
Tracing usagehttp://www.shnenglu.com/jinq0123/archive/2022/01/02/218556.html閲戝簡閲戝簡Sun, 02 Jan 2022 04:38:00 GMThttp://www.shnenglu.com/jinq0123/archive/2022/01/02/218556.htmlhttp://www.shnenglu.com/jinq0123/comments/218556.htmlhttp://www.shnenglu.com/jinq0123/archive/2022/01/02/218556.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/218556.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/218556.htmlTracing usage

(Jin Qing's Column, Jan., 2022)

Tracing is Rust log crate: https://github.com/tokio-rs/tracing

This example code outputs log to stdout and a log file, using a log filter config file, which can be automatically reloaded on change.

https://gitee.com/jinq0123/tracing-example

Dependencies

Add these dependencies to Cargo.toml:

      [dependencies]
anyhow = "1.0.52"
hotwatch = "0.4.6"
tracing = "0.1.29"
tracing-appender = "0.2.0"
tracing-subscriber = { version = "0.3.5", features = [ "env-filter", "json" ] }

    

main.rs

      mod log;
use anyhow::Result;
use std::{thread, time::Duration};
use tracing::info;
fn main() -> Result<()> {
    let _guard = log::init("./log", "example.log", "config/log_filter.txt")?;
    for i in 0..999 {
        info!(i, "Hello, world!");
        thread::sleep(Duration::from_secs(1));
    }
    Ok(())
}

    

log.rs

      //! Init log.
//!
use anyhow::{anyhow, Context as _, Result};
use hotwatch::{Event, Hotwatch};
use std::fs;
use std::path::Path;
use tracing::{debug, warn, Subscriber};
use tracing_appender::{non_blocking::WorkerGuard, rolling};
use tracing_subscriber::{fmt, layer::SubscriberExt, reload::Handle, EnvFilter};
/// Inits log.
/// Returns a WorkerGuard to ensure buffered logs are flushed,
///  and a Hotwatch to watch the log filter file.
pub fn init(
    directory: impl AsRef<Path>,
    file_name_prefix: impl AsRef<Path>,
    log_filter_file: impl AsRef<Path>,
) -> Result<(WorkerGuard, Hotwatch)> {
    let file_appender = rolling::daily(directory, file_name_prefix);
    let (non_blocking, worker_guard) = tracing_appender::non_blocking(file_appender);
    let file_layer = fmt::Layer::default()
        .with_writer(non_blocking)
        .json()
        .flatten_event(true)
        .with_ansi(false);
    let builder = tracing_subscriber::fmt()
        .pretty()
        .with_env_filter(EnvFilter::from_default_env())
        .with_filter_reloading();
    let handle = builder.reload_handle();
    let subscriber = builder.finish();
    let subscriber = subscriber.with(file_layer);
    tracing::subscriber::set_global_default(subscriber).context("set global default subscriber")?;
    reload_filter(handle.clone(), log_filter_file.as_ref());
    let log_filter_path_buf = log_filter_file.as_ref().to_path_buf();
    let mut hotwatch = Hotwatch::new().context("hotwatch failed to initialize!")?;
    hotwatch
        .watch(log_filter_file.as_ref(), move |event: Event| {
            debug!("log filter file event: {:?}", event);
            if let Event::Write(_) = event {
                reload_filter(handle.clone(), log_filter_path_buf.clone());
            }
        })
        .with_context(|| format!("failed to watch file: {:?}", log_filter_file.as_ref()))?;
    Ok((worker_guard, hotwatch))
}
fn reload_filter<S: Subscriber + 'static>(
    handle: Handle<EnvFilter, S>,
    log_filter_file: impl AsRef<Path>,
) {
    let res = try_reload_filter(handle, log_filter_file);
    match res {
        Ok(_) => debug!("reload log filter OK"),
        Err(e) => warn!("reload log filter error: {:?}", e),
    }
}
fn try_reload_filter<S: Subscriber + 'static>(
    handle: Handle<EnvFilter, S>,
    log_filter_file: impl AsRef<Path>,
) -> Result<()> {
    let contents = fs::read_to_string(log_filter_file.as_ref()).with_context(|| {
        format!(
            "something went wrong reading the file: {:?}",
            log_filter_file.as_ref()
        )
    })?;
    let contents = contents.trim();
    debug!("reload log filter: {:?}", contents);
    let new_filter = contents
        .parse::<EnvFilter>()
        .map_err(|e| anyhow!(e))
        .context("failed to parse env filter")?;
    handle.reload(new_filter).context("handle reload error")
}

    

log_filter.txt

log_filter.txt is the configure file for log. The change of this file will trigger the reload.

The log filter file must exist, otherwise it will be error:

      Error: failed to watch file: "config/log_filter.txt"
Caused by:
    緋葷粺鎵句笉鍒版寚瀹氱殑璺緞銆?(os error 3)

    

The content of log_filter.txt is a single line of filter string. A filter string consists of one or more comma-separated directives. The directive syntax is similar to RUST_LOG env val of env_logger’s.

      target[span{field=value}]=level

    

See: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/struct.EnvFilter.html

Example

  • tracing_example enables logs that:
    • target is modules of tracing_example*
  • info will enable logs that:
    • level is info
  • tracing_ex=info enables logs that:
    • target is modules of tracing_ex*
    • level is info or above
  • info,tracing_ex=debug enables logs that:
    • level is info or above
    • or target is tracing_ex* and level is debug
  • [foo]=trace enables logs that:
    • within the span foo
    • level is trace or above
  • [span_b{name=\"bob\"}] enables logs that:
    • have any target,
    • are inside a span named span_b,
    • which has a field named name with value bob,
    • at any level.

Note: span filter directive will keep effective until it exits the span.



閲戝簡 2022-01-02 12:38 鍙戣〃璇勮
]]>
Box<dyn Trait> doesn't implement the traithttp://www.shnenglu.com/jinq0123/archive/2021/12/21/217886.html閲戝簡閲戝簡Tue, 21 Dec 2021 07:09:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/12/21/217886.htmlhttp://www.shnenglu.com/jinq0123/comments/217886.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/12/21/217886.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217886.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217886.html From: 

By default a Box<dyn Trait> doesn't implement the trait of the object it contains. This means that trying to construct PeopleZoo<Box<dyn Person>> won't work out of the box and will give a type error.

Because of this, it's good practice to give a default implementation of your trait for it's boxed counterpart. This can be done by calling as_ref or as_mut on the Box and calling the references relevant method.

For just a small bit of effort you can help a bunch of people that may consume your struct.

trait Person { fn say_hello(&self); } impl Person for Box<dyn Person> { fn say_hello(&self) { self.as_ref().say_hello() } }

 

struct PeopleZoo<P: Person> {
    people: Vec<P>,
}
fn main() { let mut zoo: PeopleZoo<Box<dyn Person>> = PeopleZoo { people: vec![] }; }


閲戝簡 2021-12-21 15:09 鍙戣〃璇勮
]]>
寤鴻鏃ュ織 slog 鏀規(guī)崲 tracinghttp://www.shnenglu.com/jinq0123/archive/2021/11/24/217865.html閲戝簡閲戝簡Wed, 24 Nov 2021 10:18:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/11/24/217865.htmlhttp://www.shnenglu.com/jinq0123/comments/217865.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/11/24/217865.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217865.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217865.html寤鴻鏃ュ織 slog 鏀規(guī)崲 tracing

(閲戝簡鐨勪笓鏍?2021.11)

  • slog 涓嶆槸绔嬪嵆鍐欑洏錛屾渶鍚庣殑鍑犺鏃ュ織浼?xì)涓㈠?/p>

    • tracing 涓嶄細(xì)涓㈡棩蹇?/li>
  • slog 涓嶆敮鎸佽繍琛屼腑鍔ㄦ佹洿鏀規(guī)棩蹇楃瓑綰?/p>

  • slog 涓嶆敮鎸佷笉鍚屽寘璁劇疆涓嶅悓鏃ュ織絳夌駭

    • tracing 鍙崟鐙墦寮鏌愪釜妯″潡鐨勬棩蹇?/li>
  • 鍙戠幇涓嬈?slog panic: panicked at 'slog::Fuse Drain: Fatal(Custom { kind: BrokenPipe, error: "The logger thread terminated" })'

    • 鎼滃埌鐩稿悓閿欒錛?a target='_blank' class='url'>https://github.com/mimblewimble/grin/issues/946

      • 鍒漢鐨勮В鍐蟲柟娉曟槸: 涓嶇敤slog浜?/li>
  • slog 涓婚〉10鏈堟坊鍔犳帹鑽愪嬌鐢?tracing

  • slog 鎸夌嚎紼嬩繚瀛樹笂涓嬫枃錛宼racing 鎸夊崗紼嬩繚瀛樹笂涓嬫枃

  • tracing github star 1.9K > slog 1.2K

  • tracing crates 涓嬭澆 21M > sloggers 0.4M, slog-scope 2.6M, slog-stdlog 1.9M

  • tracing vs slog: https://www.reddit.com/r/rust/comments/kdo29n/slog_vs_tracing_which_one_do_you_prefer/

  • Rust compiler 2020騫村凡鏀圭敤 tracing錛?a target='_blank' class='url'>https://github.com/rust-lang/rust/pull/74726

  • tracing 鏇村ソ鐢?/p>

    • 鏂囨。鍙?qiáng)绀轰緥鏇村?/li>
    • 鏀寔搴撴洿澶?/li>


閲戝簡 2021-11-24 18:18 鍙戣〃璇勮
]]>
Named parameters in Rusthttp://www.shnenglu.com/jinq0123/archive/2021/11/18/217862.html閲戝簡閲戝簡Thu, 18 Nov 2021 05:14:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/11/18/217862.htmlhttp://www.shnenglu.com/jinq0123/comments/217862.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/11/18/217862.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217862.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217862.htmlNamed parameters in Rust

(Jin Qing's Column, Nov. 18, 2021)

There is no "named function parameters" in Rust, but there is an idiom for this case. If a function needs many parameters, we can define a type with all these parameters as fields, and implement Default trait for this type. Then we can input this type as the function parameter, with some of the fields specified and others using default.

foo(Config {
    a: 123,
    b: bool,
    ...Default::default(),
});


閲戝簡 2021-11-18 13:14 鍙戣〃璇勮
]]>
Rust traits act as generic constraintshttp://www.shnenglu.com/jinq0123/archive/2021/11/18/217861.html閲戝簡閲戝簡Thu, 18 Nov 2021 04:51:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/11/18/217861.htmlhttp://www.shnenglu.com/jinq0123/comments/217861.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/11/18/217861.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217861.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217861.htmlRust traits act as generic constraints

(Jin Qing's Column, Nov. 18, 2021)

Rust traits are different from interfaces of C++/Java/Go.

See: https://stevedonovan.github.io/rustifications/2018/09/08/common-rust-traits.html

Rust traits are mechanism for adding behavior to types.

Traits have 2 modes. One is interface as Java.

Another is generic constraint. Generic functions are defined over types that implemented specific traits.

The "complie-time duck typing" in C++ templates is avoided in Rust. Rust will reject a type with quack() method as a Duck type. We must pass a type which implements Duck trait. But in Go, a type with quack() method is sufficient to be used as a Duck interface.

 



閲戝簡 2021-11-18 12:51 鍙戣〃璇勮
]]>
GLIBC_2.29 not foundhttp://www.shnenglu.com/jinq0123/archive/2021/11/05/217853.html閲戝簡閲戝簡Fri, 05 Nov 2021 01:42:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/11/05/217853.htmlhttp://www.shnenglu.com/jinq0123/comments/217853.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/11/05/217853.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217853.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217853.htmlGLIBC_2.29 not found

(Jin Qing's Column, Nov. 4, 2021)

My Rust program failed when running in docker:

root@a26b49c91efb:/myapp# ldd libmyapp_py.so
./libmyapp_py.so: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by ./libmyapp_py.so)

The problem is because I build in "rust:1.56", and run in "debian:buster-slim" which is quite old. Run dpkg -l libc-bin shows the libc version is 2.28:

C:\Users\jinqing01>docker run debian:buster-slim dpkg -l libc-bin
Unable to find image 'debian:buster-slim' locally
buster-slim: Pulling from library/debian
b380bbd43752: Already exists
Digest: sha256:544c93597c784cf68dbe492ef35c00de7f4f6a990955c7144a40b20d86a3475f
Status: Downloaded newer image for debian:buster-slim
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version      Architecture Description
+++-==============-============-============-=================================
ii  libc-bin       2.28-10      amd64        GNU C Library: Binaries

Using the latest "debian:bookworm-slim" solved the problem.

Dockerfile:

FROM rust:1.56 as chef
RUN cargo install cargo-chef
WORKDIR /myapp
FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM chef AS builder
COPY --from=planner /myapp/recipe.json recipe.json
# Build dependencies
RUN cargo chef cook --release --recipe-path recipe.json
# Build application
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim AS runtime
WORKDIR /myapp
RUN apt-get update && apt-get install -y python3 python3-pip && rm -rf /var/lib/apt/lists/*
RUN pip3 install protobuf
COPY --from=builder /myapp/target/release/*.so /myapp/
COPY --from=builder /myapp/target/release/myapp /myapp/
COPY --from=builder /myapp/tests /myapp/tests
CMD ["myapp"]


閲戝簡 2021-11-05 09:42 鍙戣〃璇勮
]]>
Advice for Rust library writers about Errorhttp://www.shnenglu.com/jinq0123/archive/2021/09/02/217805.html閲戝簡閲戝簡Thu, 02 Sep 2021 03:24:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/09/02/217805.htmlhttp://www.shnenglu.com/jinq0123/comments/217805.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/09/02/217805.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217805.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217805.htmlAdvice for library writers

Idioms for Rust libraries are still forming, but if your library needs to report custom errors, then you should probably define your own error type. It’s up to you whether or not to expose its representation (like ErrorKind) or keep it hidden (like ParseIntError). Regardless of how you do it, it’s usually good practice to at least provide some information about the error beyond just its String representation. But certainly, this will vary depending on use cases.

At a minimum, you should probably implement the Error trait. This will give users of your library some minimum flexibility for composing errors. Implementing the Error trait also means that users are guaranteed the ability to obtain a string representation of an error (because it requires impls for both fmt::Debug and fmt::Display).

Beyond that, it can also be useful to provide implementations of From on your error types. This allows you (the library author) and your users to compose more detailed errors. For example, csv::Error provides From impls for both io::Error and byteorder::Error.

Finally, depending on your tastes, you may also want to define a Result type alias, particularly if your library defines a single error type. This is used in the standard library for io::Result and fmt::Result.

From: Error Handling in Rust - Andrew Gallant's Blog (burntsushi.net)



閲戝簡 2021-09-02 11:24 鍙戣〃璇勮
]]>
How to show the first few errors of rustchttp://www.shnenglu.com/jinq0123/archive/2021/09/01/217804.html閲戝簡閲戝簡Wed, 01 Sep 2021 02:55:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/09/01/217804.htmlhttp://www.shnenglu.com/jinq0123/comments/217804.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/09/01/217804.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217804.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217804.html
# How to show the first few errors of rustc

(Jin Qing's Column, Sep. 1, 2021)

When using VS Code to develop Rust, "cargo check" output maybe thousands of lines.
Use "cargo check --color=always 2>&1 | head -n100" to limit the output.

1. Change powershell terminal to cmd, because powershell fails to use pipe
    * Terminal -> New Terminal to open a terminal
    * Open the dropdown list by click the down arrow of "+" on the top-left of terminal
    * Select "Command Prompt"
2. Type and run command: `cargo test 2>&1 --color always | "d:\Program Files\Git\usr\bin\head.exe" -n100`
    * You should change the path of head.exe


閲戝簡 2021-09-01 10:55 鍙戣〃璇勮
]]>
&'a mut self is restrictivehttp://www.shnenglu.com/jinq0123/archive/2021/08/25/217794.html閲戝簡閲戝簡Wed, 25 Aug 2021 05:32:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/08/25/217794.htmlhttp://www.shnenglu.com/jinq0123/comments/217794.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/08/25/217794.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217794.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217794.html
# &'a mut self is restrictive

From https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md#5-if-it-compiles-then-my-lifetime-annotations-are-correct

```
#[derive(Debug)]
struct NumRef<'a>(&'a i32);

impl<'a> NumRef<'a> {
    // my struct is generic over 'a so that means I need to annotate
    // my self parameters with 'a too, right? (answer: no, not right)
    fn some_method(&'a mut self) {}
}

fn main() {
    let mut num_ref = NumRef(&5);
    num_ref.some_method(); // mutably borrows num_ref for the rest of its lifetime
    num_ref.some_method(); // 鉂?/div>
    println!("{:?}", num_ref); // 鉂?/div>
}
```

If we have some struct generic over 'a we almost never want to write a method with a &'a mut self receiver. 
What we're communicating to Rust is "this method will mutably borrow the struct for the entirety of the struct's lifetime". 
In practice this means Rust's borrow checker will only allow at most one call to some_method 
before the struct becomes permanently mutably borrowed and thus unusable. 
The use-cases for this are extremely rare but the code above is very easy for confused beginners to write and it compiles. 
The fix is to not add unnecessary explicit lifetime annotations and let Rust's lifetime elision rules handle it:

```
#[derive(Debug)]
struct NumRef<'a>(&'a i32);

impl<'a> NumRef<'a> {
    // no more 'a on mut self
    fn some_method(&mut self) {}

    // above line desugars to
    fn some_method_desugared<'b>(&'b mut self){}
}

fn main() {
    let mut num_ref = NumRef(&5);
    num_ref.some_method();
    num_ref.some_method(); // 鉁?/div>
    println!("{:?}", num_ref); // 鉁?/div>
}
```


閲戝簡 2021-08-25 13:32 鍙戣〃璇勮
]]>Rust callback idiomhttp://www.shnenglu.com/jinq0123/archive/2021/08/24/217793.html閲戝簡閲戝簡Tue, 24 Aug 2021 02:19:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/08/24/217793.htmlhttp://www.shnenglu.com/jinq0123/comments/217793.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/08/24/217793.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217793.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217793.html
# Rust callback idiom

Code is from: https://stackoverflow.com/questions/41081240/idiomatic-callbacks-in-rust
and
https://morestina.net/blog/793/closure-lifetimes-in-rust

```
struct Processor<'a> {
    callback: Box<dyn FnMut() + 'a>,
}

impl<'a> Processor<'a> {
    fn new() -> Processor<'a> {
        Processor {
            callback: Box::new(|| ()),
        }
    }

    fn set_callback(&mut self, c: impl FnMut() + 'a) {
        self.callback = Box::new(c);
    }

    fn process_events(&mut self) {
        (self.callback)();
    }
}

fn simple_callback() {
    println!("hello");
}

fn main() {
    let _ = Processor::new();
    
    let mut p = Processor {
        callback: Box::new(simple_callback),
    };
    p.process_events();
    let s = "world!".to_string();
    let callback2 = move || println!("hello {}", s);
    p.set_callback(callback2);
    p.process_events();
}
```

Note:
* "impl FnMut()" can only used in function declaration, not in struct declaration.
* dyn FnMut() is unsized, so it must be stored in Box
* set_callback(&mut self, c: impl FnMut()) need a lifetime for c to tell compiler that c outlives structure
    + rustc suggests `impl FnMut() + 'static`, but that is too restrictive
        - In most cases, we do not have a static lifetimed callback
* FnMut() is more restrictive than FnOnce(), but FnOnce() can only be called once
* set_callback(...) is a template method, because each closure has a different type


閲戝簡 2021-08-24 10:19 鍙戣〃璇勮
]]>Rust variable rebinding for closurehttp://www.shnenglu.com/jinq0123/archive/2021/08/22/217787.html閲戝簡閲戝簡Sun, 22 Aug 2021 09:25:00 GMThttp://www.shnenglu.com/jinq0123/archive/2021/08/22/217787.htmlhttp://www.shnenglu.com/jinq0123/comments/217787.htmlhttp://www.shnenglu.com/jinq0123/archive/2021/08/22/217787.html#Feedback0http://www.shnenglu.com/jinq0123/comments/commentRss/217787.htmlhttp://www.shnenglu.com/jinq0123/services/trackbacks/217787.html
From: https://rust-unofficial.github.io/patterns/idioms/pass-var-to-closure.html

Rust closure captures variables by reference by default.
You can use "move" keyword to change to move variables.
In most cases, some variables are moved, and some are referenced.
We can rebind variables in a separate scope before move to the closure.

```
use std::rc::Rc;

let num1 = Rc::new(1);
let num2 = Rc::new(2);
let num3 = Rc::new(3);
let closure = {
    // `num1` is moved
    let num2 = num2.clone();  // `num2` is cloned
    let num3 = num3.as_ref();  // `num3` is borrowed
    move || {
        *num1 + *num2 + *num3;
    }
};
```

Or we can use additional variables to move in the same scope:
```
let num2_clone = num2.clone();
let num3_ref = num3.as_ref();
let closure = move || {
    *num1 + *num2_clone + *num3_ref
}
```

Using separate scope can reuse the variable name, which make the closure body clearer,
but need additional indent.

閲戝簡 2021-08-22 17:25 鍙戣〃璇勮
]]>
久久只这里是精品66| 99久久成人国产精品免费| 久久天天躁狠狠躁夜夜2020 | 国产精品免费看久久久香蕉| 久久WWW免费人成—看片| 国产精品久久久久久久人人看| 国产精品禁18久久久夂久| 久久这里有精品视频| 国产日产久久高清欧美一区| 四虎国产精品免费久久| 久久国产精品一区二区| 久久亚洲日韩看片无码| 久久婷婷五月综合成人D啪| 久久精品水蜜桃av综合天堂| 色悠久久久久久久综合网| 精品999久久久久久中文字幕| 久久久久人妻一区二区三区 | 久久精品亚洲AV久久久无码| 99久久婷婷国产一区二区| 无码伊人66久久大杳蕉网站谷歌| 久久996热精品xxxx| 亚洲国产二区三区久久| 精品国产乱码久久久久久1区2区| 久久人妻AV中文字幕| 无夜精品久久久久久| 精品久久久久国产免费| 国产成人精品白浆久久69| 久久夜色精品国产噜噜亚洲AV| 亚洲国产成人久久综合区| 久久噜噜久久久精品66| 97久久精品人人澡人人爽| 久久综合久久久| 国产精品久久久久久久| 国产精品99精品久久免费| 国产精品一久久香蕉国产线看观看 | 亚洲国产精品人久久| 99热成人精品热久久669| 狠狠狠色丁香婷婷综合久久俺| 精品久久久无码人妻中文字幕豆芽| 久久婷婷五月综合97色一本一本 | 精品综合久久久久久88小说|