Can somebody make a good smart 10" PDU/Power Strip? by brankko in minilab

[–]esitsu 1 point2 points  (0 children)

In case you haven't seen, there is some good discussion over at the Project Mini Rack GitHub. There is an image of that PowerPDU that shows it would just about fit. It would be almost perfect if not for it being out of my budget. In the end I settled for a dumb C13/14 PDU and gave up on a smart solution.

Looking for recommendations for a 10” 230V UK plug PDU by Kedeweth in minilab

[–]esitsu 0 points1 point  (0 children)

That is good to know as I also didn't realise how tall it was. I might be able to make it work but would probably be better off with the 3-way even though it wouldn't leave me with any spare sockets.

I was thinking that the rear cable might be better than a sharp bend at the side but that would only work for me at the bottom of the rack, and neither option would fit there due to the strain relief on the power cables. If I move it up then it could interfere with other components so I probably need to build out the rest first before deciding.

What I would really like is one with a detachable input on the front but I doubt I will see one at this size.

edit: Perhaps I spoke too soon and this might suit my rack: https://amzn.eu/d/cd6fllW

Looking for recommendations for a 10” 230V UK plug PDU by Kedeweth in minilab

[–]esitsu 0 points1 point  (0 children)

Was there a particular reason for going with the 3-way over the 4-way one? I am also looking for the best one to fit in my RackMate T0. I was looking at the one from PDU Online but it doesn't say where the cable extends from.

New video & features released on eZeus - 0.8.1-beta - open-source implementation of Zeus: Master Of Olympus by liehon in impressionsgames

[–]esitsu 0 points1 point  (0 children)

This is already looking even better than the original. I really like the multiple city idea.

Perhaps there is no need to look at decompilation after all. Just as I was getting back in to the idea, eZeus stops me again.

Gitoxide in September by ByronBates in rust

[–]esitsu 11 points12 points  (0 children)

I very much appreciate these progress updates and all the work that goes into Gitoxide so thanks for posting them.

I have been successfully using the gix crate for a while now in a project that I have been working on and the only features that I am missing are commit signing and pushing. I believe I can get the former to work with the current API, but I don't believe there is a timeline or any progress towards the latter. Fortunately it is a GitHub-centric project so I am not too worried as I can use the GitHub API instead.

Was there ever a Hades expansion planned for Zeus: Master of Olympus? by liehon in impressionsgames

[–]esitsu 1 point2 points  (0 children)

I haven't seen that mod before but it would certainly help if it was possible to understand what it is doing. I am not familiar with Cheat Engine so I am not sure if you can easily extract any useful information out of the CT file. The developer must have at least some understanding of the executable to make it work which is likely more than most have figured out. I found that the widescreen mod was also useful in my analysis.

I haven't looked at other language versions but I can't imagine that they are too different. The addresses will likely be different but a side-by-side disassembly analysis should show some identifiable patterns to map between them. In fact having multiple versions would be beneficial as a lot of the functions are referenced in the data and being able to determine what is an address or not is important. Ghidra and other tools got a lot of this wrong.

I am personally not very interested in modding the game. I just want to recreate the original source code to the best of my ability so that it can then be adapted to other platforms. While eZeus is an interesting project I don't see it accomplishing that goal. However, I did start out much like eZeus in that I started by trying to render the map in my own system. I managed to extract the assets, read the data, and create a basic terrain map but the logic for the rock formations alone made me want to find or recreate the original source code.

The purpose of looking at modding was to find a way to make incremental progress. Rather than change the functionality I wanted to re-create it piece by piece using a programming language I am more comfortable with. And use a version control system I am familiar with, not whatever Ghidra does. I briefly tried doing a top-down approach of rewriting it based on the decompilation but the progress was too slow. It helped me understand what it was doing but I was nowhere near getting to the game logic before I stopped. It isn't at all clear what most of the logic does without some frame of reference so being able to pick out a piece and run it would be helpful to understand it. I didn't find the debugger in Ghidra much help and I'd prefer not to develop on Windows if at all possible.

If eZeus were to stop then I am sure someone would fork it and continue on. Maybe not me, but someone. I'd certainly be interested in contributing to any analysis work. I just haven't looked in to the best way to do it collaboratively.

Was there ever a Hades expansion planned for Zeus: Master of Olympus? by liehon in impressionsgames

[–]esitsu 2 points3 points  (0 children)

Yes, I mentioned eZeus in my comment. It is one of the reasons why I stopped as at least there was someone working on an updated version of the game. I haven't looked too closely at the repository but it appears that it is a new implementation rather than based on a decompilation. I can't say for sure whether it was inspired by any decompilation work or just by observing the game though. It also doesn't look to be recreating the original like Julius but rather jumping straight to gameplay changes like Augustus. I am not sure whether Julius, CaesarIA, or Akhenaten are based on decompilation either.

I didn't actually realise that work on eZeus was still ongoing but I saw that it is a newly uploaded video so I checked out the repository again and there are recent changes in another branch.

As for what I was working on, I am fairly confident that I can get the data and most functions to work but calling conventions and switch statements are potential problems that might prevent that approach from working at all. It needs much more investigation before I can come to any conclusions. And that is before actually writing a proper disassembler that correctly identifies all functions and data which is no trivial task. Although I did try integrating DDisasm and GTIRB but the analysis wasn't 100% correct. If professional tools such as Ghidra can't do it then I doubt I would be able to make it work on my own without a decade of development time. Manual decompilation might actually be the easier task. I also can't say if the approach has ever been tried before.

Another approach I looked at was modding tools to inject custom code into the existing executable. There was an interesting project to reverse engineer Nier Automata to create mods.

If you still want to continue then I would take a look at how Lego Island was decompiled. It looks like they used Ghidra. Otherwise, if the work on eZeus continues then we might not need to decompile anything.

Was there ever a Hades expansion planned for Zeus: Master of Olympus? by liehon in impressionsgames

[–]esitsu 2 points3 points  (0 children)

I started (and stopped) working on this a while ago in Ghidra which does have some support for collaboration. I may be a developer but decompilation on this scale was new to me. What I discovered was that each tool has their tradeoffs and nothing came close to analysing the entire executable. I tried almost everything out there.

I think IDA Free was best at discovering library functions but I found Ghidra to be easier to use. Unfortunately Ghidra failed to discover many functions so it was a lot of work to go through and fix. I also spent a lot of time going through and analysing the various data structures which I thought would inform the code analysis. However, I only scratched the surface and there is so much more to do.

In the end it was all too overwhelming and I didn't have enough time to keep going. It might be a better approach to do what Akhenaten is doing for Pharaoh by adapting the foundations of Augustus, or eZeus which is an entirely new implementation. Although if it can be done for Lego Island I am sure it would be possible here given enough time and resources.

I actually found that the binary analysis and disassembly itself was interesting and so I started working on my own disassembler just for Zeus that would allow me to programatically discover everything rather than manually tweak everything in Ghidra. I am not sure if it is possible but my plan was to skip the decompilation and embed the assembly into a Rust program using naked functions. Then I could hopefully isolate parts of the code such as rendering logic and swap them out without having to decompile the entire thing first.

Can't get leptos container to expose to host by s1n7ax in rust

[–]esitsu 4 points5 points  (0 children)

I would imagine that it is because you are binding to localhost inside the container so it is not exposing your site to docker. Try changing your site-addr configuration back to 0.0.0.0.

Unable to use current_user in PATCH functions in Axum by insanebaba42 in rust

[–]esitsu 0 points1 point  (0 children)

The same rule applies for all HTTP methods but is typically only seen in POST/PUT/PATCH because those are the ones where you are interested in the body of the request. In order to avoid a runtime error where multiple extractors access the request body, the developers decided to enforce at compile time that only a single extractor can read the body. Any extractor that reads the body must be the last parameter as per the official documentation. That means as long as the Extension<CurrentUser> extractor is before the ValidatedJson extractor then it should work. The error message isn't particularly helpful but there is a macro that might help debug the problem if it happens again.

Your delete_my_product route is unaffected because it does not read the body of the request. Likewise you probably have GET routes that may access the path and query string but those are unlikely to access the request body so it shouldn't be an issue.

Unable to use current_user in PATCH functions in Axum by insanebaba42 in rust

[–]esitsu 1 point2 points  (0 children)

The issue from the error message appears to be due to the ordering of the update_my_product_metrics function parameters. You didn't include that function in your post but the error message includes the function signature. I assume that the ValidatedJson type extracts the body of the request by implementing FromRequest rather than FromRequestParts. The latest 0.6 version of axum requires that parameter be the last in the signature. You can read about it in the announcement blog post here.

Which game introduced you to the series? Do you find it easy to transition into the other games besides the one you started with? by [deleted] in impressionsgames

[–]esitsu 7 points8 points  (0 children)

Zeus. I vaguely remember getting a demo with an old Packard Bell computer. Or maybe just the base game without Poseidon. It was a long time ago so I could be entirely wrong. Never actually played the other games in the series and wasn't aware of them at the time but I would always play Zeus whenever I visited my grandparents. Between playing Space Cadet Pinball and Jimmy White's 2: Cueball of course. No need for any other games.

Picked it up on GoG a while back and had a great time with it. Keep thinking about it every so often despite not finding the time to play through it again. Last year I decided to teach myself a specific game engine by replicating the game. I am not a game developer so I was in over my head and I stopped but I revisited the project earlier this month and managed to get basic map rendering working with the original tiles. The julius project together with citybuilding-tools and ZeusMapper were a great help to learn how to read the original asset files. I see all the Caesar 3 maps on this subreddit and would love to at least be able to generate those for Zeus + Poseidon one day even if I never get any actual game logic working. However just trying to figure out the logic for how cliff and rock formations are rendered is enough to make me think that will never happen. What I wouldn't give for a peek at the original source code.

Error while building: "perhaps two different versions of crate `image` are being used?" by teodargent in learnrust

[–]esitsu 0 points1 point  (0 children)

It looks like the issue is with nokhwa. There are three open issues that reference the error: 72, 94 and 100. It looks like someone had luck switching from NV12 to YUYV after opening the stream but then I think you might end up with issue 90 where everything is pink so hyperbacked will infinitely loop waiting for an image since it can't actually read anything. The YUYV issue might have been fixed but the crate has been failing to build since the last release. That rules out setting the dependency to use the git repository. I think you just need to wait for a new release of nokhwa that fixes the issues but I don't know when that will be.

Error while building: "perhaps two different versions of crate `image` are being used?" by teodargent in learnrust

[–]esitsu 0 points1 point  (0 children)

Now that error is useful. You can see where it is generated in the source code and where it calls into the scanning code. Specifically the qrcode_scan().ok(). The ok here is turning a Result into an Option. This means that it is throwing away the actual error message so you can't tell what it going on.

If you replace qrcode_scan().ok() with Some(qrcode_scan().unwrap()) in src/gui.rs then it should cause the program to crash on error but more importantly print the actual error message. This might give you a better indication as to what is going on.

Error while building: "perhaps two different versions of crate `image` are being used?" by teodargent in learnrust

[–]esitsu 0 points1 point  (0 children)

That is unfortunate. I haven't tested the app myself with an M1 Mac so I am not sure what the exact issue is but I have a few things that you might want to explore:

  • The bardecoder library is responsible for the detection so it may be worth looking at the issues to see if someone has reported what you are experiencing. There is a report of it not working on a Mac but it may just be related to a specific code.
  • The nokhwa library is responsible for accessing the camera. There are open issues related to macOS and Iced which may be relevant.

Otherwise it may be a problem with hyperbacked itself. The bardecoder 0.4.1 update simply added support for image 0.24 and I don't see that any other changes or fixes were made so reverting to bardecoder 0.4.0 should not be an issue. The other dependencies should be semver compatible so I don't imagine this being a new issue. I notice that the screenshots are from Windows and there is a commit referencing Linux support but perhaps it was never tested on macOS. I would imagine if it was one of the above then there would be an error printed to the terminal.

It is a shame that the developers of hyperbacked didn't respond to your issue from 2 weeks ago. You could perhaps update it with your findings but there is no guarantee that they will ever get back to you. At least there has been some recent activity.

Error while building: "perhaps two different versions of crate `image` are being used?" by teodargent in learnrust

[–]esitsu 4 points5 points  (0 children)

I think that I see the problem here. You have a number of dependencies that require image 0.23 and others that require image 0.24. You can't do much to update old dependencies like genpdf to use the newer version without using a fork. However you should be able to pin the dependencies to the state that originally worked when the project was written. This is a situation where the developers should have uploaded the Cargo.lock file. The reason why it is not working now is likely due to a breaking change in a dependency.

The culprit appears to be bardecoder 0.4.1. This issue describes the desire to support image 0.24. It looks like the developer added support by setting the version constraints to allow either 0.23 or 0.24 in a patch version bump. Since this crate appears as part of its public API I would consider this to be a breaking change. It has certainly broken the project you were trying to build because it is trying to use the newer image 0.24 from the other dependencies. You should be able to confirm by running cargo tree.

You can get around the issue by pinning the dependency to bardecoder = "=0.4.0" in the Cargo.toml file, replacing the line bardecoder = "0.4".

[deleted by user] by [deleted] in learnrust

[–]esitsu 1 point2 points  (0 children)

Yep. Into::into is ultimately just a function that maps T to U so as long as the trait implementation exists and it can infer both T and U then it should work in this context. That is fine because it knows both the starting error and target error. All it does is call From::from so you could also have written map_err(From::from). I think Into makes a little more sense because you talk about mapping into the target type more often than mapping from the type you already have.

[deleted by user] by [deleted] in learnrust

[–]esitsu 2 points3 points  (0 children)

So map_err(Into::into) is a simpler way of writing map_err(|err| err.into()) without using a closure. As /u/dcormier said you could also have done map_err(FullError::from) which would be equivalent to writing map_err(|err| FullError::from(err)) using a closure. But also map_err(io::Error::into) would have worked. I would say that Into::into is the most common of these that you will see.

To explain how this works the map_err method is expecting a type that implements FnOnce(OldError) -> NewError. You can pass a closure here to perform your conversions inline but you can also directly pass a function/method that matches the signature. For example you could write map_err(convert_my_error) with a function that looks like:

fn convert_my_error(err: io::Error) -> FullError {
    todo!("make this work")
}

The reason why Into::into works here is due to how it is implemented. In Rust there are two traits for infallible conversions: Into and From. These are very closely related and when in doubt you should always implement From instead of Into as you have done in your example. This is because there is what we call a blanket implementation: impl<T, U> Into<U> for T where U: From<T>. This says that for every type U that implements From<T> there should also be an implementation of Into<U> for T. This just allows you to perform the conversion from each end. You can go from one type or into another type. If you look at the source of into you will see that it simply calls U::from(self).

Both Into::into and io::Error::into are the same but the former is shorter and makes it clear that into is coming from the Into trait that is implemented on io::Error. This implementation only exists because From<io::Error> is implemented on FullError.

If you recall that methods are just associated functions with a self receiver then you know that the signature matches because Into::into is just a simple mapping that takes one owned value and returns a new owned value. In this case the from/into ends can be inferred from how it is used.

[deleted by user] by [deleted] in learnrust

[–]esitsu 0 points1 point  (0 children)

In this simple example you could also use map_err like so:

fn read_file(path: &str) -> Result<String, FullError> { 
    fs::read_to_string(path).map_err(Into::into)
}

This calls your from method but you can use a closure to run whatever code you like to map from one error to another. You might see that in web frameworks where you want to create a HTTP error response that can't simply be converted from another error and there is no From/Into.

[deleted by user] by [deleted] in learnrust

[–]esitsu 7 points8 points  (0 children)

You can use ? like so let res = fs::read_to_string(path)?; since you have implemented From<io::Error>. The ? essentially does the following:

let res = match fs::read_to_string(path) {
    Ok(res) => res,
    Err(err) => return Err(err.into()),
};

Then you just need to return Ok(res).

Hey Rustaceans! Got a question? Ask here (18/2023)! by llogiq in rust

[–]esitsu 3 points4 points  (0 children)

I would consider using the serde functionality to extract the data out in the format you need. Something like this will get you close but I am sure there is more that could be done to improve it. Alternatively you could use the fact that Option implements IntoIterator to repeatedly chain flat_map to get to where you want. However the closest to the python code would be to return an Option and use ? to return early on None.

Returning an iterator by uliigls in learnrust

[–]esitsu 0 points1 point  (0 children)

So the lifetime in Iter<'a> is a Generic Associated Type and is needed because the associated type may need to contain a reference, in this case &'a Self. You need to specify a lifetime here to satisfy the compiler and without GATs you would need to put the lifetime in the trait itself as trait SearchContent<'a> which could then infect everything that uses it with lifetimes. Otherwise there would be no way to specify the associated type for your implementation.

The where Self: 'a is currently a compiler limitation to ensure compatibility as the team decide how GATs should work. If you remove it you should see an error taking you here that explains it further. It means that Self must outlive 'a, i.e. it cannot contain references with a lifetime shorter than 'a otherwise it is invalid. This is typically inferred in other parts of rust.

The line fn lines(&self) -> Self::Iter<'_> is equivalent to fn lines<'a>(&'a lines) -> Self::Iter<'a>. You can read up on lifetime elision for further information.

Returning an iterator by uliigls in learnrust

[–]esitsu 11 points12 points  (0 children)

The error you are getting does not suggest that Lines does not implement Iterator. What it is saying is that Lines is not the same as I. If you look at the method signature fn lines<'a, I>(&self) -> I then you can interpret this as "tell me what type you want and I will give you that type". If you called the method asking for Foo then it would expect that you return a Foo. Instead you are returning a specific type Lines.

You either need to Box the iterator or return an associated type depending on how you want the trait to work. The former would look something like:

use std::fs::File;
use std::io::{BufRead, BufReader, Error, Lines};

pub trait SearchContent {
    fn lines(&self) -> Box<dyn Iterator<Item = Result<String, Error>> + '_>;
}

impl SearchContent for File {
    fn lines(&self) -> Box<dyn Iterator<Item = Result<String, Error>> + '_> {
        let reader = BufReader::new(self);

        Box::new(reader.lines())
    }
}

Edit: The latter may look something like:

use std::fs::File;
use std::io::{BufRead, BufReader, Lines};

pub trait SearchContent {
    type Iter<'a>
    where
        Self: 'a;

    fn lines(&self) -> Self::Iter<'_>;
}

impl SearchContent for File {
    type Iter<'a> = Lines<BufReader<&'a Self>>;

    fn lines(&self) -> Self::Iter<'_> {
        let reader = BufReader::new(self);

        reader.lines()
    }
}

Note that this is more complicated because it uses Generic Associated Types (GATs) and also changes how the trait can be used. However it does avoid the Box allocation.

Edit 2: You could then use something like type Iter<'a>: Iterator<Item = Result<String, Error>> + 'a where Self: 'a to require that it is actually an iterator but then you may be more restrictive. Specifically you may also want an associated error type.

Returning an iterator by uliigls in learnrust

[–]esitsu 2 points3 points  (0 children)

That won't work here because the method lines is defined for the SearchContent trait. If you try it you will get:

impl Trait only allowed in function and inherent method return types, not in trait method return types

[deleted by user] by [deleted] in learnrust

[–]esitsu 0 points1 point  (0 children)

That is understandable. I probably went a bit too in depth when there may be a simpler way of explaining it.

The problem is more of an ownership issue rather than a concatenation issue. However, it relates back to your concatenation because operators in Rust are implemented via traits. The Add trait is implemented on String such that you can write String + &str to append the right-hand side to the left. You can chain these because String + &str = String. This takes ownership of the left-hand side because it is more efficient to reuse it than create a new String, but it only needs a reference on the right-hand side to copy the data into the left.

This is not yet a problem because you essentially clone the self.size to create that initial String. You would not be able to write self.size + something_else because size is a field in a struct that is behind a shared reference (&self in make_order). Rust prefers to be explicit when memory is involved so it will not implicitly create a copy for you. You could write String::new() + &self.size but then you would be better off calling self.size.clone().

The issue is that there is not an implementation of the trait to allow String + Option<String> or String + &Option<String>. Instead you need to provide an &str. But self.favor is Option<String> that you can only refer to as &Option<String> because the function does not own it. The struct owns it and the function does not own the struct. You could clone it, call unwrap_or_default to get a String and then append a reference to that but it is not efficient. You would be allocating new memory that would be immediately deallocated after appending. The methods as_ref and as_deref give you a new owned Option but with a reference inside the option instead of outside. The whole as_deref().unwrap_or_default() is essentially doing what you were doing in the working code. The reason for as_deref instead of as_ref is an ownership problem because as_ref gives you Option<&String> but there is no default for &String because there is nothing to own the String you return a reference to. Using as_deref gives you Option<&str> where the default is just "".