https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute
#[path="../some.rs"] pub mod some;
or
pub mod some {
include!("../some.rs");
}
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
Ok(())
}
use clap::{App, Arg};
let matches = App::new("Name")
.arg(Arg::with_name("file1")
.help("arg 1")
.required(true)
.index(1)).get_matches();
let file_name = matches.value_of("file1").unwrap();
println!("file name {}", file_name);
fn print_typename<T>(_: T)
{
println!("{}", std::any::type_name::<T>());
}
* T, U, S, V: type (2nd, 3rd...)
* I : Iterator
* F : Function type - Fn, FnMut, FnOnce
* K, V: Key, Value, HashMap<K, V>
* E : Error value type, fn a() -> E { ... Err(e) => e }
* R : Trait Function Result value type
fn bara<F, R>(f: F) -> R // or Result<R, Error>
where
F: FnMut() -> R
* P : path, AsRef<Path> ...
* Ftu : Future
* St : Stream
Discard ref / ref mut https://github.com/rust-lang/rfcs/blob/master/text/2005-match-ergonomics.md https://gist.github.com/amutake/c72c634ebeee1bbe69203824bbef14d3 https://frozenlib.net/blog/2018-12-18_rust-pattern-match-2/
let mut r: Result<i32, ()> = Ok(0);
match &mut r {
Ok(x) => *x = 100,
_ => (),
}
assert_eq!(r.unwrap(), 100);
// old
match r {
Ok(ref mut x) => *x = 200,
_ => (),
}
assert_eq!(r.unwrap(), 200);
// same
match r.as_mut() {
Ok(x) => *x = 300,
_ => (),
}
assert_eq!(r.unwrap(), 300);
let mut v = Box::new(32);
{
// ref_box is &Box
let ref_box = &v;
// v_i32 is i32
let v_i32 = *v;
// &i32
let ref_i32 = v.deref();
}
{
let ref_box = &mut v;
**ref_box += 1;
// *ref_box type is &i32 : Box's Deref
// **ref_box type is *(&i32)
}
assert_eq!(33, *v);
// Pass ref variable(&v) as function argument
// auto Deref occor
let func = | a: &i32 | println!("{}", a);
func(&v); // print 33
// function call (dot operator)
// auto Deref occor
// v.pow() -> v.deref().pow(): v.deref() return &i32
//
// v. (dot operation):
// Match flow &self
// v. -> (Box::deref(&self)) -> &i32 -> i32::pow(self, ...)
let pv = v.pow(2);
assert_eq!(1089, pv);
// Cool anothor example
let mut v = Box::new(vec![1,2,3]);
// v[] call Box::deref_mut(because v is mut) -> return &mut Vec
v[0] = 32;
println!("{:?}", v); // => [32, 2, 3]
- https://stackoverflow.com/questions/33653946/dereferencing-boxt-gives-back-value-instead-of-reference/33654412#33654412
- https://stackoverflow.com/questions/42264041/how-do-i-get-an-owned-value-out-of-a-box
fn main() {
// boxed vec
let x = Box::new(vec![1,2,3,4]);
// DerefMove
// moves the vec out into y, then deallocates the box
// but does not call a destructor on the vec
let y = *x;
println!("{:?}", y);
// for any other type
let v = &vec![1,2,3,4];
// it gives an error:
let m = *v; // ERROR: cannot move out of borrowed content
}
fn unbox<T>(value: Box<T>) -> T {
*value
}
struct Foo;
impl Foo {
# this take self
fn take(self){
println!("take");
}
}
fn main() {
let a = Foo;
let b = Box::new(a);
b.take();
}
via https://users.rust-lang.org/t/questions-about-mut-t-and-move-semantics-mut-t-is-move-only/37484
let x = 0;
let y = &mut x;
let z: &mut i32 = y; // This is an implicit reborrow (equiv. to &mut *y)
let z: &mut _ = y; // This is an implicit reborrow
let z: _ = y; // This is a move
let z = y; // This is a move
fn takes_mut_i32(_arg: &mut i32) {}
fn takes_mut_t<T>(_arg: &mut T) {}
fn takes_any_t<T>(_arg: T) {}
takes_mut_i32(y); // this is an implicit reborrow
takes_mut_t(y); // this is an implicit reborrow
takes_any_t(y); // this is a move; sometimes this surprises people and there
// have been countless "bugs" filed about it
fn moving<T>(x: T) -> T { x }
let a = 1;
moving(&mut a);
It's same
{ a }
let arc = Arc::new(42);
// some better
// let arc_arc = arc.clone();
thread::spawn({
// this block binds arc as same name
let arc = arc.clone();
move || {
let arc = arc.clone();
}
})
https://frozenlib.net/blog/2018-12-18_rust-pattern-match-2/
struct V {
a: i32,
}
let mut func = | V{a} : &mut V | *a += 1;
let mut v = V{a: 23};
func(&mut v);
assert_eq!(24, v.a);
&dyn Trait
http://huonw.github.io/blog/2015/01/peeking-inside-trait-objects/
- https://doc.rust-lang.org/std/raw/struct.TraitObject.html
- 実態はfat pointer. & がついているので、refと思うが、実際は selfとvtableの構造体。
- アドレスを取るには&&dyn Traitとする
- Fn/FnMut/FnOnce inside
manually unlock, use std::mem::drop(MutexGuard)
let guard = mutex.lock().unwrap();
std::mem::drop(guard);
Dropping inconsistent between match and if
struct Goodbye;
impl Goodbye {
fn new() -> Self { Goodbye }
fn get(&self) -> Option<bool> { Some(true) }
}
impl Drop for Goodbye {
fn drop(&mut self) {
println!("Dropping");
}
}
fn main() {
let x = match Goodbye::new().get() {
Some(a) => {
println!("In match");
1
},
None => 0
};
println!("------");
let y = if Goodbye::new().get() == Some(true) {
println!("In if");
1
} else {
0
};
println!("------");
if let Some(a) = Goodbye::new().get() {
println!("In if");
1
} else {
0
};
println!("------");
while Goodbye::new().get() == Some(true) {
println!("In while");
break;
}
}
Result
In match
Dropping
------
Dropping
In if
------
In if
Dropping
------
Dropping
In while
-
Inside Rust's Async Transform
-
async lifetime ('static lifetime bound)
-
Expand .await
future.await;
// expand code
let mut pinned = unsafe {
Pin::new_unchecked(&mut future)
};
let x = loop {
match future.poll(TLS_CONTEXT){
Ready(x) => break x,
Pending => yield // generator syntax
}
};
So that, a reference of local variable in async block can across .await
async {
let x = 5;
future(&x).await;
}
//=> expand (Virtual code)
// async block's generator(generated struct closure) don't need to hold x's reference and Future + 'a (not 'static)
// then ref of local variable in async block pass as aurguments of nested async fn require 'static bound is compiled
// __Generator Variant have 'static lifetime
enum __Generator {
Variant1{x:i32}
}
impl __Generator {
fn resume() {
match self {
Variant1(x) => {
future(&x).await;
}
}
}
}
Pin<&mut T>
// ** Contract **
// Either T will never move again
// OR T: Unpin
https://rust-lang.github.io/async-book/04_pinning/01_chapter.html
Unpin は, Tのmarkerで、Pinされた後での操作制御のために使われる。 Pin にした後の操作制御であって、Pinした後は、mutでunsafeしないと取れないようにするが、Pinにするまでは、保証する必要がある
- Unpin: move していいことの意味: Pin::get_mut()で取得可能
- !Unpin: move してはいけないことの意味、unsafe なPin::get_unchecked_mut()で取得可能
For dyn Futre
- Pin<Box> + Send + 'static
e.g ItertorExt
trait Base {
fn base(&self),
}
trait BaseExt : Base {
fn base_ext(&self) {
self.base();
}
}
impl<T: Base> BaseExt : T {}
- https://doc.rust-lang.org/nomicon/subtyping.html
- https://doc.rust-lang.org/nomicon/phantom-data.html
Great Example and Answer! https://stackoverflow.com/questions/42637911/how-can-this-instance-seemingly-outlive-its-own-parameter-lifetime
struct Item<'a>{
a: &'a i32,
}
struct A<'a, 'b: 'a> {
item: &a Item<'b>,
}
lifetime of rvalue is 'static
let x: &'static = &1;
fn foo() -> 'static Foo{
&Foo{
...
}
}
'a is asummed 'static lifetime https://doc.rust-lang.org/nightly/nomicon/unbounded-lifetimes.html
fn get_str<'a>() -> &'a str;
This mean that all ref lifetime of T is longer than 'a
where T + 'a
via crate crossbeam thread
// Allocate `closure` on the heap and erase the `'env` bound.
let closure: Box<dyn FnOnce() + Send + 'env> = Box::new(closure);
let closure: Box<dyn FnOnce() + Send + 'static> =
unsafe { mem::transmute(closure) };
- 通常、A<T>に対して、TのすべてのライフタイムはAよりも長くなくてはならない。
- 例えば、Vecは, 自身のdrop時に,もしTがdropを実装している場合、T内のライフタイムも考慮する必要がある(T内にdangling pointerがあるかもしれない)。
struct A<T> {
}
dropckは、Tに関連するライフタイム(Tの自体のライフタイム、Tのfieldに関連するライフタイム)について考慮しない(しなくていい)。
impl Drop for struct A<T>{
fn drop(&mut self) {
self.as_mut().something(); // possible dangling
}
}
drop関数では、すべてのライフタイムが有効である必要があるが、
drop関数の中で T を操作することを禁止しないといけない。なぜなら、Tはその時点でDropされている可能性があるため。
* ライフタイムに関して、考慮しなくてよいとdrop-checkerに伝えるためには、#[may_dangle] を指定する.
* 下記、may_mangle は、A<T>のDropにのみ有効であって、Tにdropが実装されている場合は、チェックされる. Tを所有している場合かつTがdropを実装している場合、may_dangleは無効になる。https://users.rust-lang.org/t/phantomdata-and-dropck-confusion/26624/2
* ただし、unsafe とあるように、ユーザー任せになり、実際にTを操作することもできる(嘘ついてもいいが、動作は未定義)
+ 用はコンパイラにエラーを履かせないようにするため
unsafe impl<#[may_dangle] T> Drop for struct A<T> {
fn drop(&mut self){
}
}
-
ドロップチェッカーがdrop時にライフタイムを気にしない場合は次の2点
imple<#[may_dangle] T>
になっている場合- Strust A<T> が Tを所有していない場合(&T,*const T, *mut Tなどのポインタは所有しない、所有させるにはPhantomData)
-
may_dangle Tになっていても、A<T>がTを所有されており、Tにdropが実装されているならば、チェックされる
- なので、Vec<T> などの、自身でメモリを確保している場合は、PhantomData<T>をフィールドに追加し、Tがdropを実装している場合、中で参照をチェックできるようにしている(ドロップチェッカーに教えている)
-
つまるところ、TがDropを実装していない場合、T がdropするとき、内部の参照を触らないので、Dropckはチェックを無視できるが、TがDropを実装している場合は、内部の参照に触る可能性がある(あってもなくても)のでDropckはこれを阻止する必要がある。AがTのraw pointerのみであると、Dropckは検知できないが、PhantomDataを置くことによって、チェックできるようにしている(may_dangleであっても)。
-
注)may_mangleを付けなければ、Dropckはされるので、PhantomDataは必要ない。A::new()がTの生成よりも後であれば、問題なく動く。Tの生成がAよりも後にしないといけない場合は、may_mangle, PhantomDataの組み合わせが必要になる
-
https://users.rust-lang.org/t/phantomdata-and-dropck-confusion/26624
use std::path::Path;
let a = 1;
let b = "b";
let c = "c".to_string();
let d = Path::new("d");
let s = format!("{} {} {} {}", a, b, c, d.display()); // => String
// Read
use std::fs::File;
use std::io::{Read};
let mut f = File::open("./src/main.rs")?;
let mut buf = String::new();
f.read_to_string(&mut buf)?;
let _a = buf.lines().map( |line| { println!("{}", line.trim()) } ).collect::<Vec<_>>();
use image;
use image::{GenericImageView};
use imageproc::drawing;
use imageproc::rect::Rect;
use orbtk::prelude::*;
let mut img = image::open("test.jpg")?;
// draw rectangle
drawing::draw_filled_rect_mut(&mut img, Rect::at(10, 10).of_size(50, 50), image::Rgba([255u8, 255u8, 0u8, 255u8]));
// save image
img.save("result.png")?;
// show image
let data: Vec<u32> = img.to_rgba()
.pixels()
.map(|p| {
((p[3] as u32) << 24) | ((p[0] as u32) << 16) | ((p[1] as u32) << 8) | (p[2] as u32)
})
.collect();
let image_data = Image::from_data(img.width(), img.height(), data)?;
Application::new()
.window(move |ctx| {
Window::new()
.title("image")
.size(img.width(), img.height())
// or pass file-path : .child(ImageWidget::new().image("result.png").build(ctx))
.child(ImageWidget::new().image(image_data.clone()).build(ctx))
.build(ctx)
})
.run();
// This function say
// For caller:
// I return a reference of somthing,
// This return value can only be used in the scope of the reference you give (lifetime 'a)
fn Bara<'a>(a: &'a str) -> &'a str {
# something
}
fn Bara<'a>(a: &'a str) -> Object<'a> {
# Build Object
}
sturct A {
a: i32,
}
fn foo(a: &'static A){}
fn boo(){
// temporary lifetime is promoted to 'static
let a = &A{ a: 23 }
foo(a)
}
T: 'a : You allow T which has some reference values
struct Bara<'a> {
a: &'a str,
b: Vec<&'a str>,
}
T: 'static : You want T which don't have reference Type value, except &'static variable
struct Bara {
a: &'static str,
b: Vec<&'static str>
}
it's ok, Because "Hello World" is &'static str type, bara.a's "'a" is 'static
struct Bara<'a>{
a: &'a str,
}
fn main() {
let bara = Bara {a: "Hello World" };
}
T: Fn() -> i32 + 'static : clojure (Fn) must have all variables 'static
T: Fn() -> i32 + 'a : clojure (Fn) have some reference values
Almost use this pattern
let a = stream::iter([iterator]).map(|x| spawn()).buffer_unordered([concurrency num]).collect::<Vec<_>>();
a.await;
Full Example
use tokio::prelude::*;
use futures::stream::{self, StreamExt};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>>{
let fetches = stream::iter(0..=1000)
.map(|x|
tokio::spawn(
async move {
println!("{} :cur thread {:?}", x, std::thread::current().id())
}
)
)
.buffer_unordered(10)
.collect::<Vec<_>>();
// Note if you want ordered items, use buffer(10) instead of buffer_unordered
fetches.await;
Ok(())
}
use std::io::Write;
use image;
use image::png::PngEncoder;
use image::GenericImageView;
use base64;
use web_view::*;
let img_data = image::open("test.jpg")?.to_rgba();
let (width, height) = img_data.dimensions();
let mut encoded_image = Vec::<u8>::new();
let encoder = PngEncoder::new(&mut encoded_image);
encoder.encode(img_data.into_raw().as_ref(), width, height, image::ColorType::Rgba8)?;
let img_base64 = base64::encode(&encoded_image);
let html_content = format!("<html><body><h1>Hello</h1><img src=\"data:image/png;base64,{}\" \\><body></html>", img_base64);
web_view::builder()
.title("image")
.content(Content::Html(html_content))
.size(640, 480)
.user_data(())
.invoke_handler(|_wv, _arg| Ok(()))
.run()
.unwrap();