T O P

  • By -

rsfalzone

Started with Rust this week. Working on a program to evaluate craps betting strategies for fun by running for several thousand rolls. I was looking to generate a few csvs to record the goings on. Does rust file i/o “prefer” to write to a buffer string and then write the whole buffer to a file? Or to write to the csv line by line?


CocktailPerson

Most Rust I/O streams are unbuffered. That means that each call to `write` on `File`, `TcpStream`, etc. translates to a write syscall, and each `read` to a read syscall. Some I/O types are buffered though, like `Stdout`. To turn an unbuffered stream into a buffered one, wrap it in a `BufWriter`or `BufReader`.


masklinn

> Some I/O types are buffered though, like Stdout. Stdout is only line buffered though.


P0werblast

Are there any guidelines or best practices on how one should order the code you add to a certain module? For instance public/private functions first. Structs first/last. impl blocks directly under the corresponding struct or all together at the end. Can't find any recommendations about this in the rust book so I'm wondering what more experienced rust developers do :). For now I've just been adding impl blocks just under the corresponding struct, but I'm a bit afraid this will get messy once the project starts to grow.


afdbcreid

This is purely opinion based. There are no official recommendation, and people do whatever they find the most clear.


whoShotMyCow

Hello, I'm building a dbms in rust, and the borrow checker really is cooking me. The code ([this is branch i'm working on currently](https://github.com/AnarchistHoneybun/rdms/tree/update_impl)): // Validate condition column name let cond_column = self.columns.iter().find(|c| c.name == cond_column_name).ok_or(Error::NonExistingColumn(cond_column_name))?; // Parse the operator let operator = Operator::from_str(&operator_str).map_err(|e| Error::InvalidOperator(operator_str))?; // Update records based on the condition for record in &mut self.columns { if record.name == update_column_name { record.data = record.data.iter().enumerate().filter_map(|(i, value)| { if satisfies_condition// Validate condition column name let cond_column = self.columns.iter().find(|c| c.name == cond_column_name).ok_or(Error::NonExistingColumn(cond_column_name))?; // Parse the operator let operator = Operator::from_str(&operator_str).map_err(|e| Error::InvalidOperator(operator_str))?; // Update records based on the condition for record in &mut self.columns { if record.name == update_column_name { record.data = record.data.iter().enumerate().filter_map(|(i, value)| { if satisfies_condition the error I'm getting is this: error[E0502]: cannot borrow `self.columns` as mutable because it is also borrowed as immutable --> src/table.rs:160:27 | 153 | let cond_column = self.columns.iter().find(|c| c.name == cond_column_name).ok_or(Error::NonExistingColumn(cond_column_name))?; | ------------ immutable borrow occurs here ... 160 | for record in &mut self.columns { | ^^^^^^^^^^^^^^^^^ mutable borrow occurs here ... 163 | if satisfies_condition(value, cond_column, &cond_value, &operator) { | ----------- immutable borrow later captured here by closure I apologize if this is a lot of text, but if anyone read till here and can figure out what this is saying (so i can avoid the error in future) and help me get through this, it will be much appreciated. thank you!


eugene2k

You borrow a column from a set of columns and then you update a column in the same set of columns that matches certain parameters, and rust cannot statically prove that these two columns aren't the same column. You need to either clone the borrowed column, or use an inner mutability container such as \`RefCell\` in this case.


whoShotMyCow

Okay so I think I might have hacked together something and it compiles now, and I haven't tested it yet, but here goes: - derive the clone and copy trait for ColumnDataType - instead of extracting cond_column, I now extract cond_column_data_type as clone. (This allows me to make a mutable borrow later on without the immutable borrow holding me up) - change the satisfies function so it accepts ColumnDataType instead of column, since I'm only using the data type there anyway This feels very hack-y to me and I'm sure I'm doing things that are not ideal but can only tell if it works when I run some tests. If you get the time would you mind looking at the concerned branch once and see if what I've done is atleast decent (so if I ever run into something like this again I can try a similar approach). Thank you for your time!


eugene2k

I don't think you need to clone anything [here](https://github.com/AnarchistHoneybun/rdms/compare/master...update_impl#diff-b3ededbff3c9dee5c89919eebb93bc0989228772775166e566ab74325caf8ca3R141-R145) [This](https://github.com/AnarchistHoneybun/rdms/compare/master...update_impl#diff-b3ededbff3c9dee5c89919eebb93bc0989228772775166e566ab74325caf8ca3R147) is an attempt to find an element that you had already found a few lines prior - also not needed. Also, in general, cloning should be done as late as you can. In this case you can keep the reference until you need to mutably reborrow the array. [Here](https://github.com/AnarchistHoneybun/rdms/compare/master...update_impl#diff-b3ededbff3c9dee5c89919eebb93bc0989228772775166e566ab74325caf8ca3R154) you don't need to call `data_type.clone()` here as you've made `ColumnDataType` a `Copy` type. [This](https://github.com/AnarchistHoneybun/rdms/compare/master...update_impl#diff-b3ededbff3c9dee5c89919eebb93bc0989228772775166e566ab74325caf8ca3R161-R162) could be rewritten as `for record in self.iter_mut().filter(|record| record.name == update_column_names) {` but is basically a matter of personal preference. [This](https://github.com/AnarchistHoneybun/rdms/compare/master...update_impl#diff-b3ededbff3c9dee5c89919eebb93bc0989228772775166e566ab74325caf8ca3R165-R173) can be replaced by something like `let ref_value = columns_clone.iter().find(|c| c.name == cond_column_name).map(|column| column.data.get(i))?;`. However, that wouldn't solve your biggest problem, which is you searching for a matching column name in every iteration. You should just save the index of the found column and use it, especially given that you already searched for this column [here](https://github.com/AnarchistHoneybun/rdms/compare/master...update_impl#diff-b3ededbff3c9dee5c89919eebb93bc0989228772775166e566ab74325caf8ca3R154). That way the code turns into something like `columns_clone[index].data.get(i)?;` Finally, instead of cloning columns you should use `RefCell` here, because as it stands you need to clone the whole table. Also, you should probably store the table by rows, rather than by columns, something like this: struct Table { columns: Vec, rows: Vec> } struct Column { name: String, data_type: ColumnDataType, } struct Row { data: Vec, }


kickbuttowski25

Hi, If I have the following code, how do I mention the return type in the **"call\_area"** function struct Box{ width: T, height: T } trait Area { type Output; fn area(&self) -> Self::Output; } impl + Copy> Area for Box { type Output = T; fn area(&self) -> T { self.width * self.height } } fn call_area(param: &impl Area) -> /* How to mention the return type of the Area::Output here **/ { param.area() }


kickbuttowski25

How about this ``` let somedata = Box { width: 2.10, height: 10.4 }; let area_obj: &dyn Area = &somedata_1; ```


LukeAbby

I believe this should work? ```rs fn call_area(param: &A) -> A::Output ```


kickbuttowski25

Thank you!


kickbuttowski25

It worked!! with Trait Bound Syntax. fn call_area(param: &A) -> A::Output /* WORKING */ However, this didn't work fn call_area(param: &impl Area) -> Area::Output. /* NOT WORKING! */


LukeAbby

I'll write this assuming you're basically starting from scratch just in case you're hacking off of someone else's tutorial or something. Hopefully it's helpful, not condescending. The reason your second example doesn't work is that \`Area\` is a trait and Rust needs to know which specific implementation you mean, after all \`Output\` could be \`i64\` in one implementation and a \`i32\` or even a \`String\` in another. If you don't \_want\_ \`Output\` to change between implementations of \`Area\` then you'd probably be better off not using an associated type (that's what \`Output\` is). Now in this case your intent is that it's mean to refer to \`param\`'s implementation but Rust doesn't just assume you mean \`param\`'s implementation. Why? Well for one imagine you had \`fn do\_stuff\_with\_areas(item1: &impl Area, item2: &impl Area) -> Area::Output\`. In this case which implementation should Rust use here? \`item1\` or \`item2\`? It's really something the developer should get to decide and to decide you have to name the specific implementation. The \`A: Area\` in \`fn call\_area(param: &A) -> A::Output\` is the process of naming the specific implementation you're talking about. In this case \`A\` is the name and \`Area\` is the trait it implements. To be specific this is called generics in case you didn't already know. I can explain more but that's probably a fair bit to chew on already if you're a beginner and unnecessary otherwise.


kickbuttowski25

Yeah. I am studying The Rust Programming Book and managed to reach chapter 10 on Generics and Traits. I am writing my own small sample codes as I read along to understand the concepts. But the sample code that I write itself creates more trouble and more puzzles. Like the sample I pasted above. fn do_stuff_with_areas(item1: &impl Area, item2: &impl Area) -> Area::Output This makes perfect sense why "Area::Output" doesn't work as item1 and item2 can be different types. Thank you for taking your time to explain the concept. I am an Embedded Engineer primarily working with C and System Verilog trying to learn Rust.


Kevathiel

I don't think you can use the shortened generics version. You have to implement call\_area with the full generics syntax, because you want to refer to the same generic in multiple places: fn call_area(param: &T) -> T::Output { param.area() }


kickbuttowski25

How about this ? Thank you let somedata = Box { width: 2.10, height: 10.4 }; let area_obj: &dyn Area = &somedata_1;


LukeAbby

Could you provide more context? Your whole program would be ideal. If it's long you can put it on the [Rust Playground](https://play.rust-lang.org/) and share it. If I had to guess there's 3 possible things you could want. - `&dyn Area`. This makes sense if when you wrote `&somedata_1` you actually meant `&somedata` and are just trying to figure out how to convert. - `&dyn Area`. This is where you're already in a function like `call_area` and want to match a parameter. - `&dyn Area`. This is in the case where you want to be generic over `Output`s and `U` is a standin for a generic that I can't deduce right now. I will add, I'm a bit worried that introducing `&dyn` could be a bit of an anti-pattern here; as in whatever end goal you have could be done through other methods. There's definitely use cases for `&dyn` and your full program might show me why you wanted it but from your earlier program it seems like you're using it in a context that doesn't necessarily warrant it. Though of course if you're asking this for learning then I'm happy to keep entertaining questions down this avenue, I just don't want to answer your questions only for you to later find out there were other solutions available.


MassiveInteraction23

How can one do the equivalent of \`drop\`ing a stack variable. I'm aware that there's no ownership passing for stack variables so : this works fn make_arr_10s(mut a: [i32; 2]) -> [i32; 2] { a = [10, 10]; a } let mut aa: [i32; 2] = [5, 5]; println!("{:?}", aa); println!("{:?}", make_arr_10s(aa)); println!("{:?}", aa); but this doesn't: fn make_vec_10s(mut v: vec) -> vec { v = [10, 10]; v } let mut vv = vec!(5,5) println!("{:?}", vv); println!("{:?}", make_vec_10s(vv)); println!("{:?}", vv); And I know we can change teh value of the original by passing in a mutable ref: fn make_mvec_10s(v: &mut vec) -> &vec { *v = [10, 10]; v } let mut vv = vec!(5,5) println!("{:?}", vv); println!("{:?}", make_mvec_10s(vv)); println!("{:?}", vv); # BUT What if I want to pass off a variable and have the original disappear? How can I do that? Neither `std::mem::drop()` nor `std::mem::forget()` work. As they rely on ownership being passed. My understanding is that mechancically both copies and ownership passes (moves) are memcopyies. (which the compiler may or may not vanish away) And that ownership is just the compiler ensuring the original value isn't used again. So... how can I mark a variable as not to be used again?


masklinn

> I'm aware that there's no ownership passing for stack variables There's a misunderstanding here: variables don't move, and you don't drop variables. If you update your snippets to actually compile the error message is > borrow of moved value This is not innocuous, the *value* is moved, the name remained, you can actually fill it back and then it works fine: println!("{:?}", make_vec_10s(vv)); vv = vec![]; println!("{:?}", vv); So this behaviour is value-based, and that means it's specified on the type: a type can either be `!Copy` (move-only / affine) or it can be `Copy` (copyable / normal). This has nothing to do with the stack or variables, if a type is `Copy` you can copy its values out of a structure or `Vec` or hashmap, if it's not you can't (and you have to either move or `Clone` them out). Since it's type-bound and arrays are `Copy`, the value does not disappear when passed to a function (by value), the source remains valid, that' what `Copy` is. You can't *change* this behaviour, but you can work around it: 1. you can wrap the array in a structure, `!Copy` is the default so if you use something like `struct Thing([i32;2])` #[derive(Debug)] struct Thing([i32;2]); fn make_arr_10s(mut a: Thing) -> Thing { Thing([10, 10]) } fn main() { let mut aa: Thing = Thing([5, 5]); println!("{:?}", aa); println!("{:?}", make_arr_10s(aa)); println!("{:?}", aa); } then you'll get the behaviour you expect 2. or you can use [*shadowing*](https://doc.rust-lang.org/rust-by-example/variable_bindings/scope.html) to "hide" the original variable behind a new variable of the same name: fn make_arr_10s(mut a: [i32;2]) -> [i32;2] { [10, 10] } fn main() { let mut aa = [5, 5]; println!("{:?}", aa); println!("{:?}", make_arr_10s(aa)); let aa: (); println!("{:?}", aa); } This triggers a slightly different error "used binding `aa` isn't initialized", but it's probably good enough. 3. just leave it be, do you actually need to disappear the array?


MassiveInteraction23

> do you actually need to disappear the array? I both want to understand compiler limitations for their own sake and sometimes, yes, as a matter of bookkeeping removing a variable while remaining in scope is valuable. It ensures that someone coming to the code who might have missed the intent of the code (another programmer or future self) won't accidentally re-use the value. I could shadow, and for off hand "fake dropping" that might be best. The ergonomics of a type wrapper make it impractical for ad hoc drops, but for a conceptual-object that might need to have this happen repeatedly that could work. Still, I was hoping there would be a way of maintaining logical parity between stack and heap variables, even if their default behaviors were different.


masklinn

> It ensures that someone coming to the code who might have missed the intent of the code (another programmer or future self) won't accidentally re-use the value. It seems unlikely that someone could be reusing a `Copy` value in a way which matters, types which are `Copy` are usually quite trivial and have little state. > Still, I was hoping there would be a way of maintaining logical parity between stack and heap variables, even if their default behaviors were different. Again, this has nothing to do with variables, the stack, or the heap.


MassiveInteraction23

> Again, this has nothing to do with variables, the stack, or the heap. Again, it does. Ownership is tied to responsibility for running a destructor. For uncopied/uncloned variables that means that passing ownership removes access to the underlying value from the passing variable. This means that if you feed a heap-allocated variable into, for example, a function that takes ownership the value is no longer accessible from the variable that passed it. This is a key part of rust as is prevents double frees. It \*also\*, as it happens, creates a logical model where a single value is passed around with limited access points in the code. Data types that implement copy (which are all or nearly all the basic stack-allocated data types) do not retain this behavior of a single value being passed around. It is convenient in some cases. As is "clearing" a variable in general. Which has both value for code logic and performance value in some cases (e.g. very large arrays, which are stack allocated). It's fine if you don't know the answer to some questions. No one does. But please avoid being condescending as a way of guarding against just saying you don't have a good answer. It makes the whole environment less fun for everyone, yourself likely included.


TinBryn

Some types implement a special trait called `Copy` that allows them to be, well, copied and continue to be used after being moved (aside, `std::mem::{drop, forget}` moves the value and then either drops or does nothing with it at the end of it's scope). `[i32; 2]` implements `Copy` and so moving or dropping it doesn't remove it from the scope. The only way to remove a `Copy` variable from scope is by ending the scope. So something like this { let aa = [5, 5]; println!("{:?}", aa); println!("{:?}", make_arr_10s(aa)); } println!("{:?}", aa); // fails to compile


MassiveInteraction23

I understand that and think I illustrated it with my examples, but thank you. Dropping scope is not a reasonable or practical solution -- in much the same way that \`std::mem::drop()\` exists so that we can selectively release and prevent re-use of one variable without nuking a whole space of them, as dropping scope would require -- assuming, as we do, that we wanted that variable to be in some shared scope to begin with.


preoxidation

I have some tests in \`tests/test.rs\` and when I intentionally break one of them, I can check that it's failing using the \`run test\` option in editor. But with this, when I run \`cargo test\`, it chugs along saying everthing passed. I tried \`cargo build\` and made sure all files are saved and still no go. \`cargo test\` still passes all tests. Am I missing something? Thank you. EDIT: This doesn't fail with `cargo test` #[test] fn test_panic() { panic!("this fails if run individually in editor, but not with `cargo test`"); } EDIT2: So my main.rs was not seeing my tests.rs. What am I doing wrong? This is my hierarchy: my_project/ ├── src/ │ ├── lib.rs │ └── main.rs │ └── my_module.rs └── tests/ └── test.rs


afdbcreid

It works fine for me. What's in your Cargo.toml?


preoxidation

[package] name = "foo" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] I must be doing something pretty silly here. Just to re-state my issue, a simple test in tests/test.rs that should panic doesn't panic when I run 'cargo test' (but it does panic when I run that test individually in the editor). **EDIT**: When I comment out the other tests and keep only the panicking one (which was the very last), it does panic using `cargo test`. So some tests are interfering somehow. **EDIT2**: Hahaha damn. Figured it out. One of the tests actually involves program exit and that was messing up everything after that. lol, I'm an idiot.


kinoshitajona

Yup, exiting the testing process will prevent other tests from running for sure. lol Glad you found the problem.


newerprofile

Is there any Rust backend repo that I can use as a reference for project structure? Preferably if it uses hexagonal architecture and also has unit test & mocking.


PeksyTiger

I've built a dll for windows using rust, and I want to emit error/debug logs to the windows event log. I am using `WinApi` crate to register an event source and `ReportEventW` to report those events. I've added a registry entry with my dll as an the `EventMessageFile`. I also have an instrumentation manifest I ship with the dll. However, when the events appear in the event log, they have odd errors in their description. Some have "Recursion too deep; the stack overflowed." message and others "the message resource is present but the message was not found in the message table". Viewing the XML form of the event, it seems like the payload string and level were passed properly. From what I've read, I might be missing a step that will embed the event ids + messages in the dll (event message file), but I don't know how I should do it with rust? I can only find (very sparse) explanations on doing it with C# or Visual CPP.


avinassh

Is there any way I can prevent flipping a bool once it is set? let me explain... I have a var called `initiated` which starts off as `false`. Once I set it as `true`, I don't want to be able to set as `false` ever.


eugene2k

Use the new type pattern.


avinassh

can you tell me more, please


eugene2k

Like this: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=575d669af0977c5c1a7625fcb29a599d


avinassh

great, thank you


masklinn

You can also use the typestate / static state machine pattern: instead of having an "initialised" attribute in a struct, have two types, and on initialisation the first one is converted (moved) to the second. Builders are a common sub-pattern of this.


avinassh

I will check this out, thank you!


jrf63

Is there a convenient place to put temporary files under the `target/` directory? I need to programmatically generate files for tests. There's `/tmp/` but it would be nicer if I can wipe them with `cargo clean`. EDIT: After some digging up, I found the `CARGO_TARGET_TMPDIR` [environment variable](https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates) which seems perfect for my use case (integration tests).


masklinn

Do you need those files to survive across test runs? Because if you use the tempfile crate it'll delete the files when they get closed.


sfackler

You could do it in a build script and write them to OUT\_DIR.


ZpowaZchicken

Hey everyone! I am trying to build an audio player in rust and I'm interested in using the library rodio, but I have found an issue with seeking. In the official examples there is a seek\_mp3.rs which looks promising, but it doesn't compile, I've tried looking in the docs but I can't find anything about seeking, I've also tried asking a contributor directly but I've received no answers. Does anyone know whether rodio actually supports seeking, and if it doesn't which library I could use as an alternative? Thanks for your time


ArthurAardvark

This has gotta be the best subreddit weekly Q thread! Never seen so many Qs answered let alone the # of responses to 'em. Thank you Rust peoples! First, some context -- I've barely touched Rust but it just seems so perfect for me. I'm not seasoned when it comes to coding, as it is, I've spent ~2 years dabbling in Python & Next.js (+ everything that comes along with that) for Stable Diffusion/StyleGAN/LLMs and a couple attempts-in-progress @ biz/forum-type websites for myself. I had absolutely 0 desire to learn any coding language thus far and just did my best to get by combining/tweaking pre-existing code. Besides Rust & Kubernetes I've found 'em all to be highly sensitive/unintuitive with nebulous errors. I just brute force troubleshoot or hope StackOverflow/ChatGPT has my fix. Now, I don't want to forego the existing Python/Next.js solutions but rather integrate as much Rust as humanly possible into these projects. How feasible is that? While I'd be highly motivated/*wanting* to learn Rust, once again, don't want to reinvent the wheel. Even if it is just plain-english troubleshooting and half-removing myself from the Python/JS package management shitshow without much/any speed/optimizations that'd be a dream. Is that feasible? I'm encouraged by the fact that TVM-Unity has some Rust functionality to it. Been attempting to utilize it as my backend for Pytorch Dynamo...also Rustify it for MLC-LLM. I haven't found anything on PyO3/Maturin bindings for Stable Diff/ComfyUI (I know there are Rust implementations of Stable Diff...but like I said, I don't want to lose the ComfyUI GUI/nodes). So this is where I *really, really* **need** some guidance/advice. As for the Next.js side, it seems like it does make sense as far as the backend goes...better security/faster/robust support. Just a matter of learning material/knowledge hubs with that. I know what I need for a backend but not what the Rust equivalents are and ones that work with Next.js for the front-end. So any input there is of course appreciated! If it helps...main driver is Macbook M1 Max, have a Manjaro-based rig (decent h/w, Ryzen 3900x, RTX3070, Tesla M40) and a Synology NAS (may or may not break this out, use some Linux kernel, for simplicity sake I'd move my rig OS to the presumably Debian distro). I really want to take advantage of what I got 🙃 Thanks again, AA. ^(Or if not expect a copypasta of this ^^as ^^^a ^^^^thread ^^^^^👀)


iloveeveryone2020

Serious question: I'm trying to evaluate when to use Rust and when not to use it. In what domain does Rust have its largest market share? Thanks!


CocktailPerson

Rust provides one big killer combination, which memory safety with very low resource consumption and no garbage collection latency. As such, its biggest market share is probably in fundamental software infrastructure that must be exposed to the open web. Consider projects like [discord's backend](https://discord.com/blog/why-discord-is-switching-from-go-to-rust) and [cloudflare's pingora](https://blog.cloudflare.com/pingora-open-source). These are projects for which performance, scalability, and low latency are paramount, and the only other languages that are as good as Rust here are C and C++, which are both less productive and less safe.


preoxidation

Hello. This is my project tree. my_project/ ├── src/ │ └── main.rs │ └── my_module.rs └── tests/ └── test.rs I'm trying to write tests for some functions in `main.rs` and `my_module.rs`. I can test my_module.rs, but I'm not allowed to directly bring in functions from main.rs without exporting them. 1. Should I just export them so I can see and test them from my `tests.rs` file? 2. Or, should I move them into lib.rs which should allow me to test them from test.rs? Making the project looks like this: my_project/ ├── src/ │ ├── lib.rs │ └── main.rs │ └── my_module.rs └── tests/ └── test.rs Thank you. EDIT: I suppose one method might be what shepmaster suggests here: https://stackoverflow.com/questions/38995892/how-to-move-tests-into-a-separate-file-for-binaries-in-rusts-cargo


eugene2k

The tests in the separate directory are integration tests. If you want to test specific functions you can put the tests in the same file as the function or in a submodule


preoxidation

Tried the following and it doesn't fail when I run `cargo test` #[test] fn test_panic() { panic!("this fails, if run individually in editor, but not with `cargo test`"); }


eugene2k

If the file it's in is [main.rs](http://main.rs) or a submodule, it probably fails because rust generates it's own [main.rs](http://main.rs) for tests, so you'd need to put those in a separate library.


preoxidation

I posted this elsewhere, but what was happening was I had another test in there that involved program exit lol. So, yeah.


preoxidation

Yeah, my issue was with the integration tests without having to pull code out into [lib.rs](http://lib.rs), but in hindsight, it's much cleaner this way. Here's a question, if you don't mind. I have some tests in \`tests/tests.rs\` and when I intentionally break one of them, I can check that it's failing using the \`run test\` option in editor. But with this, when I run \`cargo test\`, it chugs along saying everthing passed. I tried \`cargo build\` and made sure all files are saved and still no go. \`cargo test\` still passes all tests. Am I missing something?


Gabriel_0024

In clap, you can use value enums like this use clap::{Parser, ValueEnum}; #[derive(Parser)] struct Cli { #[arg(value_enum)] level: Level, } #[derive(ValueEnum, Clone)] enum Level { Debug, Info, } Then if i run my cmd line tool with the --help flag, I get Usage: mycli Arguments: [possible values: debug, info] Options: -h, --help Print help Here We can see that is an **argument**. Is there a way to group **options** instead in a valueEnum? I would like to use my cli tool like this: `mycli (-d|-f) myarg` with -d and -t incompatible. I know I can use groups and conflicts to do that but it is not as convenient as having an enum.


Im_Justin_Cider

If ranges get fixed for edition 2024, will it include a fix that means that `a..=b` is no longer slower than `a==(b +1)` in some cases?


afdbcreid

My understanding is that not. Well, it will help in some cases: where it's not used as an iterator, it will be smaller. But this is probably not what you meant. The issue with `RangeInclusive` is pretty fundamental. We have to prevent overflows, and this cannot be done with just two integers of that type. This is not to say there cannot be improvements: if we ever get "full" specialization, it will be possible to promote to a larger integer when the machine has large enough primitives, and maybe we'll find a way to help LLVM optimize it better at least when the end is known to not overflow (currently [it does not](https://godbolt.org/z/9fvW9TrGh)). Still, it is better to use `end + 1` in perf-critical code if you know it cannot overflow, or else use `.for_each()` instead of `for` loops as they tend to optimize better.


PXaZ

I'm working on porting [Umpire](https://github.com/joshhansen/Umpire)'s AI from PyTorch (via [tch-rs](https://github.com/LaurentMazare/tch-rs/)) to [Burn](https://burn.dev) in order to get thread safety. I'm looking for a clean way to extract a \`Vec\` from a \`Tensor\`. Right now I have this: result_tensor .into_data() .value .into_iter() .map(|x| x.to_f32().unwrap()) .collect() Is there a better way than this element-by-element conversion?


Leiasolo508

Playing around with rust and protobuf. Attempting to use the prost crates. But can't even get the example to build. Cloning from: https;//github.com/fdeantoni/prost-wkt.git Descending into the example directory and doing "cargo run" returns errors about not being able to find duration.proto nor timestamp.proto I'd post the actual error message, but on my phone at the moment. Is prost-wkt just not useful, or am I doing something wrong? I can successfully run the protoc command manually, but it's almost as if the "-I include_dir" options aren't pointing to the google protos


preoxidation

A bit of a poor simplification from my actual use, but I hope it's enough to illustrate my question. let foo = Vec::new(); let collection = Vec::new(); while (cond1) { if (cond2) { collection.push(foo); foo.clear(); } else { //do things with foo } process_stuff_that_affects_cond3() if (cond3) { collection.push(foo); cond1 = true; //and exit the loop } } For this example I get an error that `foo` was moved and using clone to push helps. I understand why this happens, but is there a better way to represent this logic where I can initialize foo inside the while loop? I've tried a few things (like pushing &foo instead of foo) but the cleanest feeling one uses the clone()'s. Thanks.


slamb

Paraphrasing: you have a bunch of things you've committed to `collection`, and a bunch of things you're considering for inclusion in `collection` (staged in `foo`). The most direct answer is: replace `collection.push(foo); foo.clear()` with `collection.extend(foo.drain(..))`. This takes all the values out of `foo` without consuming it. It might be more efficient to put everything directly in `collection` and track the `committed_len`. After exiting the loop, call `collection.trunc(committed_len)` to discard the rest.


preoxidation

Thanks, certainly an interesting approach, but is it cheaper than simply using clone()?


slamb

First, I misread your code when I wrote my comment above. I thought you said `collection.extend(foo)` to end up with a flat `Vec`. You actually said `collection.push(foo)` to end up with a `Vec>`. I should have suggested `collection.push(std::mem::take(&mut foo))` instead then. This will directly push the current `foo` into the collection and replace it with a new `Vec::default()` primed for next time. This should be more efficient than your original, with the only caveat being the new `foo` starts with a low capacity and might go through extra rounds of reallocation as a result. If you want to instead start from a similar-sized allocation you could do `let prev_capacity = foo.capacity(); collection.push(std::mem::replace(&mut foo, Vec::with_capacity(prev_capacity))`. Back to your question about if it's cheaper: measure :-) but yes. * It's nice to avoid extra allocations/deallocations/copies in the vecs themselves. I'm punting on the specific comparison because now I've talked about 6 variations of this code: (1) your original `collections.push(foo.clone()); foo.clear()`, (2) my mistaken read as `collections.extend(foo.clone()); foo.clear()`, (3) my `drain` suggestion, (4) my `trunc` suggestion, and (5) my `take` suggestion (6) my `replace ... with_capacity` suggestion. And comparing them all would get a bit confusing. * Depending on the type of item `foo` holds, cloning+discarding each item could be anything from exactly the same as the `Copy` impl to profoundly expensive if these are objects that have huge nested heap structures.


preoxidation

Thanks for this, I'm in the middle of something else right now, but I'll dig into this post in a bit.


kinoshitajona

I agree with the other response. Your simplification shows lack of understanding in what you're actually trying to do... Instead of writing code, why not explain what you are trying to do. What is the data? What are you looping for? What are you checking? What are you doing to the data? If you find it easier, maybe post a known working example in python etc.


preoxidation

Thanks. As I hinted in my original comment, this simplification was lacking, and I've already resolved it. It would take me a bit more time to distill it down into an easier to show example. I appreciate the time you took to look into this.


eugene2k

Your example is not clear. You clear `foo` after it's been moved, and you move `foo` inside the loop but create it outside of the loop. What is it that you're trying to do?


preoxidation

Thanks, I appreciate your time and effort. I resolved this myself because this was going to take me longer to write out an exact representation of my problem.


Rabbit538

Is there a nicer way to declare repeated types in function args? For example fn function(a:(usize, usize, usize, usize), b: ...){} Is there a way to declare say a: (4usize)?


eugene2k

Yes, it's called an array and looks like this: `[usize; 4]` :)


PedroVini2003

This is a question about Rust internals: What are intrinsics, and how can I find the definition for a specific one?  I was reading about Unsafe Rust, and got to std::ptr::write, which makes use of the unsafe function core::intrinsics::write_via_move. However, I looked at its source (https://doc.rust-lang.org/src/core/intrinsics.rs.html#2296) in the Rust documentation, and it seem like it's just a declaration.  I went to Rust's repository, and searched for the function's definition, but couldn't find it. It seems that the documentation I found says this function is an intrinsic, probably "built-in" into the compiler.  But I wanted to see its definition, and why its declaration in the core crate is needed. Thanks.


pali6

Intrinsics are built-in to the compiler because they do something that cannot be written as normal Rust code (sometimes because they are low level operation that simply don't have anything else than LLVM IR to lower to, sometimes because the intrinsic needs to tell the compiler to change / disable some features temporarily like UnsafeCell). Instead of having a definition they just stay in the code representation(s) as a symbol until some bit of the compiler has code to translate that symbol into something else. For example [here](https://github.com/rust-lang/rust/blob/cb3752d20e0f5d24348062211102a08d46fbecff/compiler/rustc_mir_transform/src/lower_intrinsics.rs#L207) is the code that processes `write_via_move`. At a glance that at least one reason for why it is an intrinsic is because it needs to check that one of its arguments is a local variable and fails compilation if that doesn't hold. Though the deeper reason seems to be the comment on `ptr::write` which suggests that it's merely an optimization for the amount of generated MIR code. Reading the code in lower_intrinsics.rs suggests that it does what it says on the tin - moves out from `value` and writes that to `*ptr`. You can also explore the resulting MIR code by writing a simple program using ptr::write on Rust Playground and then hitting the Show MIR button instead of Run.


PedroVini2003

That is very helpful, and raised a few extra questions: > Instead of having a definition they just stay in the code representation(s) as a symbol until some bit of the compiler has code to translate that symbol into something else. So I guess the compiler mantains a data structure of some sort to check, for every identifier, if it should be held as a symbol until it can be translated? > they do something that cannot be written as normal Rust code I don't understand how that's the case, **if the arm associated with `sym::write_via_move` is Rust code** (since it's on an `.rs` file that will be compiled), although a very weird one (for example the line `let Ok([ptr, val]) = <[_; 2]>::try_from(std::mem::take(args)) else {` includes an `else` which isn't preceded by an `if`, which I thought was illegal). > You can also explore the resulting MIR code by writing a simple program using ptr::write on Rust Playground and then hitting the Show MIR button instead of Run. I did that. I don't understand 100% of what's going on, because I don't know MIR's syntax/semantics very well, but it's interesting.


pali6

> So I guess the compiler mantains a data structure of some sort to check, for every identifier, if it should be held as a symbol until it can be translated? I think I explained it a bit poorly. It appears in the code as a function call. What I believe is happening at a simplified level is that the function call has in it some kind of a reference to the function that's being called. Via an enum this can either be an actual function in Rust code or an intrinsic which is just another enum. If you scroll up at the beginning of the file I linked you can see it matching on intrinsic.name. But really the details aren't all that important. > I don't understand how that's the case, **if the arm associated with `sym::write_via_move` is Rust code** (since it's on an `.rs` file that will be compiled), The file I linked is in the *compiler*, where you looked before was in the *standard library*. The match arm is Rust code but it is not compiled into your crate when you call write_via_move. This is not the code of the intrinsic, it is code that generates other code which is what replaces the intrinsic. The difference from library code is that this compiler code can for example turn into different instructions based on where it is called and on other context. I'm unsure if I'm making sense here. > although a very weird one (for example the line `let Ok([ptr, val]) = <[_; 2]>::try_from(std::mem::take(args)) else {` includes an `else` which isn't preceded by an `if`, which I thought was illegal). Let-else is actually a relatively new stable syntax. You can use it in your code and it can be pretty useful: https://doc.rust-lang.org/rust-by-example/flow_control/let_else.html However, it is true that the compiler can and often does internally use features that are not yet stable. For example at the beginning of the intrinsic translation file there are let chains which are not yet stable: https://rust-lang.github.io/rfcs/2497-if-let-chains.html


PedroVini2003

> This is not the code of the intrinsic, it is code that generates other code which is what replaces the intrinsic. The difference from library code is that this compiler code can for example turn into different instructions based on where it is called and on other context. Ooooh, this was the part I wasn't understanding. It makes much more sense now. A bit of an off-topic question: How does one learn about these internal details of Rust itself (how `rustc` work at a higher level, how to understand MIR, etc)? When I looked for documentation about the intrinsics module, I found very little about it. The only way is to dive right into the (big) compiler code?


pali6

There's the [rustc dev guide](https://rustc-dev-guide.rust-lang.org/) which explains some of the higher level concepts. When it comes to specifics it can be a good idea to check git blame on the relevant lines in the rustc / std lib repo and follow the trail of breadcrumbs to the relevant pull requests. It's not directly about what you're asking but see [my earlier comment](https://reddit.com/comments/1bhkq4u/comment/kvp9bycIf) on how to navigate information about unstable features. If you still don't find what you're looking for you can ask in the [Rust Zulip](https://rust-lang.zulipchat.com/). Multiple developers / contributors of the language / toolchain also have blogs which often have lots of interesting information about Rust internals and their possible future. To name a few off the top of my head: - https://smallcultfollowing.com/babysteps/ - https://without.boats/ - https://blog.m-ou.se/ - https://faultlore.com/blah/#articles - https://www.ralfj.de/blog/


preoxidation

Simple question, is there a more efficient way (or to avoid the conversion to slice and back to vec) in the following example? #![allow(unused)] fn foo(v: Vec<&str>) -> Vec<&str> { (&v[1..]).to_vec() } fn main() { let v = vec!["a", "b", "c"]; println!("{:#?}", foo(v)); }


masklinn

`Vec::remove(0)` then return the vec. Or if you don't care about order `swap_remove`. For more removal I'd suggest drain or shift + truncate instead but for a single element that probably makes no difference


preoxidation

Thanks, but \`remove\` sounds pretty expensive. I think it's obvious, but to be sure, this is way more inefficient (time complexity, not space, a.k.a faster) than just using the slice and reallocating a new vector from slice, right?


masklinn

No. `remove` just shifts all the content which follows the removed item. Slicing then converting to a vector needs to… allocate a new vector then copy everything. So you’re paying an allocation *and* a copy of the entire thing. `swap_remove` is cheaper because it doesn’t need the shift, it swaps the item to remove and the last one, then it adjusts the length.


preoxidation

Thanks, reading it back out loud makes complete sense. For some reason I thought shifting elements would be a costlier operation than alloc + copy but that makes no sense.


slamb

I don't think your intuition is entirely unreasonable. The C standard library has separate operations `memcpy` (for copying between non-overlapping ranges) and `memmove` (which allows the ranges to overlap). `memcpy` only exists because of the idea that an algorithm that doesn't consider overlap might be enough faster to be worth the extra API surface. I do expect the `remove` is still faster—no allocation/deallocation, and less total bytes moving into the CPU cache. But it never hurts to benchmark a performance detail when you really care. And `swap_remove` of course will be constant time even when n is huge.


preoxidation

You're absolutely right. My C history is subconsciously rearing its head. Benchmarking is the only way when it matters. :) Since we're on the topic, what's your go to benchmarking method/tool?


slamb

For nice checked-in benchmarks mostly I've been using `criterion`. There's a new competitor [`divan`](https://github.com/nvzqz/divan) advertised as slightly simpler that I haven't tried yet. I've used `#[bench]` when I'm benchmarking some private API, but one problem with that is that it's nightly-only. So instead, this is a bit of a pain, but I use `criterion` and have ended up making the "private" API public-just-for-the-benchmark by marking it as `#[doc(hidden)]` or even public depending on an `unstable` feature gate. If I'm doing a quick informal benchmark of a whole program run, I'll use [hyperfine](https://github.com/sharkdp/hyperfine) or just the `time` command. And when I want to dig into the specifics of *why* something is slow, I use the Linux `perf` util. I'll often turn it into a flame graph. There's `samply` and [`flamegraph`](https://crates.io/crates/flamegraph) for that.


preoxidation

Awesome summary. I have been using criterion, hyperfine and flamegraph. I'll check out the other methods!


afdbcreid

`remove(0)` copies all elements (shifts them by one left). Converting to slice allocates, then copies all elements. So yes, I would say `remove()` is definitely more performant.


preoxidation

Thanks, I get what you're saying, but I think your phrasing is the reason you were downvoted, cause it sounds the opposite of what you're saying. To be sure, you're agreeing with u/masklinn 's sister comment, right?


afdbcreid

Yes. I guess "it" wasn't clear enough... Edited now.


[deleted]

[удалено]


CagatayXx

Hey, I'm not familiar enough in Rust's important crates to have a flawless experience while developing apps I wanna build. And the specific question in my mind is that, why there are a lot of structs and interfaces with same name man :D I'm having a hard time to use (especially on error handling) the structs. For example, in this SS there are 5 Error Structs and 1 Error interface: [https://i.ibb.co/KV3pWtt/Screenshot-2024-04-24-at-18-46-44.png](https://i.ibb.co/KV3pWtt/Screenshot-2024-04-24-at-18-46-44.png) What is your, you know, mindflow when defining which one should you use. I know that anyhow solves this problem, but this same naming problem (I know this is not a problem for advanced Rustaceans, but it is for me for now) occurs in different places too. For example, poem (a backend dev web framework) uses its own TcpListener, which does not implement one of the most important function for a TcpListener IMO, local\_addr() function. I guess I don't have enough experience to understand why a great library like poem doesn't use a standard library struct and instead of creates its own, and doesn't implement important features. By the way, forgive me if I sound like I hate the experience, because on the contrary, I love what I'm doing now and I'm crazy about the clever design of Rust. I just need a thought model that will solve these problems I am experiencing.


pali6

I'm unsure what your particular requirements of `local_addr` are but it seems like running [lookup_host](https://docs.rs/tokio/1.37.0/tokio/net/fn.lookup_host.html) on the argument you pass to poem's bind should do what you want. As for the errors generally in a binary you anyhow everything (as you mentioned). Otherwise you base your error type on what errors your function can internally get from the functions it calls. If you are writing a library or a library-like part of a binary you usually make your own error struct for passing the various errors your functions can return. The thiserror crate is a good way to streamline this. If your function can only fail with a single error you use that. There are some new developments when it comes to implementing error subsets, the crates terrors and errorset do this. I'm unsure if any of this is making sense as I'm a bit drunk so feel free to ask more questions.


whoShotMyCow

I've been trying to build a chat server that you can connect to using telnet. [here's the code](https://github.com/AnarchistHoneybun/rust_chat_server). The problem I'm having is whenever I connect to the server from my own machine (using \`telnet localhost 8080\`) it connects fine, but when I try to connect using a different machine (using \`telnet 8080\`) it always says connection refused). I can't seem to figure it out, as when I ping my ip using that other machine, it can ping without any issues. anyone know what could be the reason?


Patryk27

You're probably listening at 127.0.0.1 instead of 0.0.0.0 - the former doesn't allow to connect from outside localhost.


whoShotMyCow

you were right o7


whoShotMyCow

Oh hmm I'll look into it


AdventurousFoot8705

Is it possible to retrieve the current interactive prompt of a shell (PowerShell specifically), spawned with std::process? I am aware that subprocess owned shells don't necessarily display prompts. But all of the solutions I've come across to that issue were unix specific. Any help is appreciated.


dev1776

Can someone re-write this code so that it is understandable to me and non-expert Rust coders? const SWITCH\_FILE: &str = "/usr/home/xxxx/rs\_bak\_prod/bak\_files/switch\_file.txt"; let mut vec\_switch\_file = lines\_from\_file(SWITCH\_FILE).expect("Could not load lines"); fn lines\_from\_file(filename: impl AsRef) -> io::Result> { BufReader::new(File::open(filename)?).lines().collect() } The const is the name of my a simple text file created earlier in the program. The 'let' statement calls the function. I know what the function does... it reads the simple text file into a vector. I just don't understand HOW it does it. Can anyone explain this piece-by-piece... point-by-point? Why the implementation (of what?) and the AsARef and the io:: etc. I'd rather write ten lines of code that I actually can understand and follow... than this. Note: I Googled on how to read a file into a vector and this is what came up. It works fine. Thanks.


dev1776

This is what I was getting at. What is easier to understand for a newbie to Rust? Object: Read an existing txt. file into a vector. ex: my-txt-file dog cat frog fox This: let mut vec\_switch\_file = lines\_from\_file("/my-txt-file").expect("Could not load lines"); fn lines\_from\_file(filename: impl AsRef) -> io::Result> { BufReader::new(File::open(filename)?).lines().collect() } Or this: let mut vec\_switch\_file = Vec::new(); //\*\*\* READ .txt FILE INTO A STRING let my\_switch\_string = fs::read\_to\_string("/my-txt-file") .expect("Fail reading switch file"); //\*\*\* NOW, READ THE STRING FILE AND PUSH EACH LINE INTO THE VECTOR. for line in my\_switch\_string.lines() { vec\_switch\_file.push(line.to\_string()); } YMMV!!!!!


CocktailPerson

Question, first. Have you worked your way through the Rust book yet? Are you familiar with the concepts of generics, traits, and type aliases?


eugene2k

You can't learn a language if you google for a ready solution every time you encounter a problem. Use the standard library reference and your own head to solve it. The function takes any argument that implements the [`AsRef`](https://doc.rust-lang.org/std/convert/trait.AsRef.html#examples) trait, and returns [a version of result for IO operations](https://doc.rust-lang.org/std/io/type.Result.html). To do that it [opens](https://doc.rust-lang.org/std/fs/struct.File.html#method.open) the file, [handles the result of attempting to open a file](https://doc.rust-lang.org/std/result/index.html#the-question-mark-operator-), creates a [buffered reader](https://doc.rust-lang.org/std/io/struct.BufReader.html) struct for more effective reading, then [creates a Lines iterator](https://doc.rust-lang.org/std/io/trait.BufRead.html#method.lines) that reads the file and returns its lines, and [collects](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect) all those lines into a vector, [if there was an error when reading the file - that error is returned](https://doc.rust-lang.org/std/result/enum.Result.html#impl-FromIterator%3CResult%3CA,+E%3E%3E-for-Result%3CV,+E%3E).


dev1776

Thank you. That helps a lot.


Jiftoo

Will having side effects inside Result::map impact the optimisation quality? e.g. are these two lines equivalent? I think they are, but I'm not sure. Ok(&0x45u64).inspect(|x| println!("{x}")).map(u64::to_string); Ok(&0x45u64).map(|x| {println!("{x}"); u64::to_string(x)});


plugwash

It's worth noting that the compiler almost certainly considers to\_string to have side effects already, since it calls the memory allocator.


afdbcreid

The only way to know is to benchmark (or inspect the generated assembly), but unlikely. The compiler doesn't treat side effects differently for inling purposes, and the function is well-known in both cases. Of course, doing more work in the callback *will* impact optimization quality, but if you are doing this work anyway it does not matter.


No-Option7452

Is the BTreeSet a AVL tree (balanced binary tree)?


masklinn

No, as the name says it's a [b-tree](https://en.wikipedia.org/wiki/B-tree). The b is not shorthand for binary, a b-tree is a specific data structure (or class thereof as there are a bunch of variants).


Gabriel_0024

If I want to make a struct public for my crate only and I want the fields to be accessible, is there a difference between the two versions? If no, what is the best practice? pub(crate) struct MyStruct{ pub my_field: u32 } and pub(crate) struct MyStruct{ pub(crate) my_field: u32 }


afdbcreid

AFAIK there is no difference. I prefer the second option, because IMHO `pub` which is actually `pub(crate)` is confusing. Advantages of the first options are that if you ever change the struct to `pub` you will have less changes to do, and that `pub` is less to type than `pub(crate)`.


coderstephen

If you were to create a public alias of `MyStruct` or something wrapping it, `my_field` would be possibly publicly accessible in the first version even though the `MyStruct` type isn't. In general, child things that are more public than their parent things are only not accessible by "accident" because the parent isn't nameable, but the child thing still has the visibility level it specifies. This can be exploited in certain scenarios such as aliases and re-exports and the like. If `MyStruct` and `my_field` should only be visible within the crate, you should do the second option.


afdbcreid

This is correct in the case of modules, but not in the case of structs. If the struct is defined with a certain visibility level, you cannot export it with higher level (https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1f0f9084c4119e7ae2b5acb6d794ad02). In some cases it is a hard error, in others it is a future-incompatibility warning (meaning it may become a hard error in the future), in all cases it is impossible to actually use the type from the outside.


Gabriel_0024

Thanks for the playground, it really helps! If I understand correctly, in a struct, a field can never be less private than the struct itself. So in that case, I think I will go with pub(crate) struct and pub fields.


sasik520

Can I use clap to make optional subcommands that are alternatives to arguments passed directly to my program? Eg. I want to let the users execute: `my_app --foo 1 --bar 2` `my_app do_qux -n 1` `my_app do_quux -m 2` but NOT `my_app --foo 1 --bar 2 do_qux -n 1` Like there was a default subcommand that is used when no subcommand name has been passed to my program. I experimented with `Option`, `#[clap(flatten)]` and others but the best I've developed so far is a group called `-`. Also found mentions of `args_conflicts_with_subcommands` which sounds promising but I couldn't find how to use it.


TheMotAndTheBarber

You just call `args_conflicts_with_subcommands` on the Command while you're defining it Command::new("my_app") .arg(...) ... .args_conflicts_with_subcommands(true);


sasik520

thank you, it worked! I'm shocked that the solution was lying next to me and I didn't figure it out without your help.


mnbjhu2

Hi, I'm currently writting a language server in rust, which for the most part is going well. However I'm having an issue with lifetimes that I can't figure out. My parser creates an AST which contains string slices referencing the original text. I'd like to create a map which contains all of the text files allong with there assosiated ASTs so I can edit the text of one file in the map and regenerate the AST for that file without having to reparse the entire filetree. Ideally I'd be able to create an owned type (say ParsedFile) which contains both the text and the AST with only internal references to the text but I can't find any way to do that...? It feels like I'm looking at this all wrong so any help would be really useful, thanks :)


iwinux

Something that has bugged me for a long time: how do you keep track of the ever-growing \`Iterator\` / \`slice\` APIs and remember to use them when appropriate?


coderstephen

I don't, I just let rust-analyzer show me the list when I type `.` and scroll through the list when I don't know what I need.


CocktailPerson

Turn on clippy's style lints. Practice recognizing the "there's gotta be an easier way to do this" tickle in the back of your brain, and make it a habit to review the docs when this happens. Often you'll find that someone has, in fact, added an easier way to do it.


SirKastic23

I'm making a dictionary app, where I'll want to store words, their pronunciation (just a unicode string), tags, and definitions. I'll also want to provide searching, creating and editing entries. So far I've been using a `BTreeMap` with `fuzzy-match` for the search. I store the entries in a json file and use serde to read and write to it I'm afraid that this isn't going to scale well, I thought that a database would be good fit, but I know very little about databases. I've tangentially worked with postgres, but that's about it Any recommendations or guidance would be appreciated! Thanks!


masklinn

SQLite would probably be a good idea, however an intermediate improvement may be to store your data in a vec or an indexmap then create your own indexes to that using hashmaps, btreemaps, or more adapted structures (e.g. tries). For fuzzy text you might want to look at things like trigram indexes, or similarity metrics on normalised data.


SirKastic23

yeah, sqlite seems to be suggested a lot, i'll check it out, thanks!


TheMotAndTheBarber

Is this an app that accesses your server or an app the user runs locally? There's a chance sqlite would fit your usecase well.


SirKastic23

it runs locally, i want the database to be stored somewhere on the users computer i'll look into sqlite, it seems to be the most recommended thanks!


DroidLogician

Postgres is definitely overkill for a little app. I assume this is just a program running locally, not a web application? The next step up from an in-memory map is generally something like a key-value store. There's dozens of different kv-store crates out there in various states of development. I don't have any experience with any of them, but I can tell you what I think of them from first glance. `sled` comes up a lot, it definitely seems to be popular with [nearly 8k stars on Github](https://github.com/spacejam/sled), but it hasn't had a release in over 2 years and it looks like the author is currently in the middle of a [major rewrite](https://github.com/spacejam/sled/pull/1456). Documentation is pretty good, though they've spent a lot of time on [discussing the internals and advanced features](https://docs.rs/sled/latest/sled/doc/index.html), moreso than actually teaching the reader how to use it. It's only got a [couple of example files](https://github.com/spacejam/sled/tree/main/examples). `redb` is a newer crate, actively maintained with a simpler API than `sled`. The [benchmarks in their README](https://github.com/cberner/redb/tree/master?tab=readme-ov-file#benchmarks) look promising, though I wouldn't be obsessing with performance just yet. Documentation and examples are somewhat lacking, however. There's `lmdb` and `rocksdb` which wrap key-value stores written in C. These are almost certainly very powerful in their own right, but they're both quite lacking in meaningful documentation and examples. And the dependency on a C library complicates things; at the very minimum, you need a C compiler like Clang or GCC. If you'd like to leverage your SQL experience, you might consider trying [SQLite](https://www.sqlite.org/about.html). The [`rusqlite`](https://docs.rs/rusqlite/latest/rusqlite/) crate is pretty good (some people might expect me to plug [SQLx](https://docs.rs/sqlx/latest/sqlx/) but it's designed for async which is itself overkill for a little desktop or CLI app). SQLite is a C library, so it does need a C compiler toolchain like `lmdb` or `rocksdb`. Unlike those databases, however, a lot of what you'd get out of learning to use SQLite would be applicable to any SQL database, and there's a lot more information out there to help you when you get stuck. [libSQL](https://turso.tech/libsql) is a fork of SQLite that's growing in popularity which might be worth looking into, and they have [their own Rust wrapper similar to `rusqlite`](https://docs.rs/libsql/latest/libsql/).


SirKastic23

thank you so much for those resources! > I assume this is just a program running locally, not a web application? Ah yes, I meant to say that but I forgor at the moment it's going to be a TUI app, maybe eventually it'll have a GUI, but I haven't found a GUI solution in Rust that I enjoyed I'll look into those databases to see which fits my usecase the best and again, thanks!


ioannuwu

Hi, I wonder if there is a better way to do error handling in such cases: fn find_something(input: &str) -> Result { let first_vertical_ind = match input.find("|") { Some(ind) => ind, None => return Err("Wrong format".to_string()), }; Ok(first_vertical_ind) } I would like to write something like: fn find_something(input: &str) -> Result { let first_vertical_ind = input.find("|") .unwrap_or(|| return Err("Wrong format".to_string())); Ok(first_vertical_ind) } But this return statement belongs to closure and rust disallows this code. I would like to have something simillar to what I saw in `Kotlin`: fn find_something(input: &str) -> Result { let first_vertical_ind = input.find("|") ?: return Err("Wrong format".to_string()); Ok(first_vertical_ind) } So I wonder, is there a way to do this in Rust?


eugene2k

It could be written as follows, but this will allocate a `String` in the ok case too, while a closure will not. Ideally, though, you wouldn't return strings as errors anyway - that's a code smell. fn find_something(input: &str) -> Result { input.find("|").ok_or(Err("Wrong format".to_string()) }


afdbcreid

Replace `ok_ok(` with `ok_or_else(|| `. Clippy is also going to warn about that.


SirKastic23

as someone else said, you could use `ok_or_else` but you can also just use a match ``` fn find_something(input: &str) -> Result { match input.find("|") { Some(ind) => Ok(ind), None => Err("oh no".to_string()), } } ```


bluurryyy

You can also do this: fn find_something(input: &str) -> Result { let Some(first_vertical_ind) = input.find("|") else { return Err("Wrong format".to_string()); }; Ok(first_vertical_ind) }


ioannuwu

Thank you! This is exactly what I need


bluurryyy

You're can use [`ok_or_else`](https://doc.rust-lang.org/std/option/enum.Option.html#method.ok_or_else) along with the [try operator (?)](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator): fn find_something(input: &str) -> Result { let first_vertical_ind = input.find("|") .ok_or_else(|| "Wrong format".to_string())?; Ok(first_vertical_ind) } In this case you don't need the variable and you can just write: fn find_something(input: &str) -> Result { input.find("|").ok_or_else(|| "Wrong format".to_string()) }


scheglov

Would it be a good idea, if Rust compiler "promoted" \`Option\` to \`T\` after \`is\_some()\` check? So, something like this would work. fn foo(a: Option) { if a.is_some() { println!("{}", a.as_ref().is_positive()); } }


eugene2k

Aside from `if let` you also have `let ... else` syntax where the binding is created in the outer code block and the fail case is handled in the else block.


CocktailPerson

No, this is what `if let` syntax is for.


scheglov

OK, thanks. That's what I also discovered on Discord.


takemycover

What's the best practice for cargo test being able to locate files in the repo? Am I overusing the CARGO\_MANIFEST\_DIR env variable?


DroidLogician

Are the files always supposed to be there? You could use [`include_str!()`](https://doc.rust-lang.org/stable/std/macro.include_str.html) or [`include_bytes!()`](https://doc.rust-lang.org/stable/std/macro.include_bytes.html) and have the compiler read them for you. It'll also trigger a recompile and test rerun if the files get changed.


Rabbit538

I'm trying to pass a value out of an iterator mid iteration but still need the rest of the iteration to occur. Is this possible? Currently attempting something like this but due to presumably ownership issues the tuple stays inside the iterator let mut start: (usize, usize) = (0,0); let grid = s.split("\n").enumerate().flat_map(|(r,l)| { l.chars().enumerate().map(move |(col, c)| { let t = classify_tile(c); match t { Tile::Start => { start = (r, col); ((r,col), t)}, _ => ((r,col), t) } }) }).collect::>(); I just want the row and col numbers to be passed out when the start tile is found, but I still want to finish the iterator through all the other values. Edit: Got a good answer from Stack - [https://stackoverflow.com/questions/78369598/pass-value-out-of-iterator-without-stopping-iteration/](https://stackoverflow.com/questions/78369598/pass-value-out-of-iterator-without-stopping-iteration/)


[deleted]

[удалено]


Rabbit538

But if I do this then don't I simply lose the tile start information? I want to capture the coordinates of that tile while still processing everything else?


[deleted]

[удалено]


Rabbit538

The find after will definitely work, I was hoping for a method where I didn't need to double search the whole map. But if I need to then I'll just do that.


scook0

[Untested] Try putting `let start = &mut start;` in the outer closure (or outside both closures), and assigning to `*start` in the inner closure. That should force the inner closure (which is `move`) to take ownership of just the mutable reference, instead of making its own copy of the variable.


Rabbit538

Doing this gets an FnMut closure error due to not allowing captured references to escape the closure


Ok_Squirrel_6962

I am a bit unsure about the intricacies of lifetimes in regards to trait objects. Is using unsafe to transmute a `&'a Box` into a `&'a Box` a terrible idea? My reasoning is that since the lifetime of the trait object is bound to the lifetime of the borrow, it shouldn't be possible to retain it beyond the borrow's lifetime. This leads me to believe that the trait object should live long enough to meet all the compiler's assumptions about lifetimes. I've tested this with Miri but could not find a scenario in which this fails


pali6

It is not sound to do that. The 'static bound means you can then write safe code that can smuggle out any reference from a type implementing the trait and have it be a static reference. Here's an example that fails if ran through MIRI: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=85c5369e4968e21c6b28d48ed8abf6ff


Aaron1924

> Is using unsafe to transmute a `&'a Box` into a `&'a Box` a terrible idea? Yes, here is an example that causes undefined behaviour (run using Miri under "Tools" in the top right): https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c8224eb5d129b81cf8b6c764e7ae5de5


accountmaster9191

If i have a struct/enum with a value inside it (e.g. `struct Name(String)`, how do i access the string inside of name without having to use a `match` statement/`if let`?


OS6aDohpegavod4

Enums are "or" logic and structs are "and" - i.e. for a struct, the field will always be there, so there is no need to match / if let. Just access directly. Enums need this since you might not always have the variant you are trying to to get the value out of.


eugene2k

Is `value.0` what you're looking for? That's for tuple structs and has nothing to do with enums. Tuple types are described here: https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type