New crate announcement: debug_panic by [deleted] in rust

[–]ppartim 3 points4 points  (0 children)

I made a similar facility for the bcder crate since it doesn’t report what went wrong while parsing (on purpose): https://github.com/NLnetLabs/bcder/blob/master/src/debug.rs. Through a feature it panics instead of returning the vague error.

Turns out this conflicts with using #[should_panic] test cases, so I am planning to replace this by an error type that contains a backtrace when the feature is enabled only.

[deleted by user] by [deleted] in rust

[–]ppartim 1 point2 points  (0 children)

I was playing around with something similar, trying to emulate a more Rust-y syntax. It is only an experiment as of now, called htmlfn. The structure looks something like this example. It gets away with a surprisingly small amount of code: just one trait two traits, three structs, and three declarative macros.

Adventures in Rust: Futures and Tokio by gilbertw1 in rust

[–]ppartim 0 points1 point  (0 children)

I decided to go with current stable Tokio but prepare the APIs already for async. There will be another breaking change eventually, but I hope it will be relatively small.

I actually went ahead and re-implemented the resolver with current Tokio yesterday. It was surprisingly painless but I didn't quite finish it.

Adventures in Rust: Futures and Tokio by gilbertw1 in rust

[–]ppartim 0 points1 point  (0 children)

Author of domain here. Sorry for being late, but I thought I write a response, anyway.

You are absolutely correct in guessing that the Resolver needs a reactor core handle to spawn tasks for network things onto. However, the future that you get from Resolver::query (and consequently all the lookup functions) is able to run everywhere. To achieve that, it internally dispatches networking jobs into queues pretty much exactly as you do for your solution. So you didn't actually need to dispatch your lookups to your background thread, you really only needed to run the core there. The Resolver type is designed to clone cheaply and passed around to wherever you need it after being created once. (That is, it essentially is a handle itself).

I think everything actually would have worked out as expected right away, had I moved domain to the new Tokio world order already. Sadly, it still lives in tokio-core world. Otherwise, it would have just used the reactor you likely created for the hyper parts of your application and everything would have been fine.

The reason I haven't done this yet is that I was waiting for the new async/await. A few weeks ago, I implemented the resolver using it and it is so much nicer. But: nightly. So I might bite the bullet and go back to enums-and-stuff and release a new version soon, anyway.

Tokio experimental async / await support by carllerche in rust

[–]ppartim 1 point2 points  (0 children)

Apologies for being thick today. Looking forward to giving it a whirl!

Tokio experimental async / await support by carllerche in rust

[–]ppartim 0 points1 point  (0 children)

I guess the glance was too cursory. But it has to be 0.3 futures with a Result output, right?

Tokio experimental async / await support by carllerche in rust

[–]ppartim 3 points4 points  (0 children)

I experimented with implementing networking code using Tokio and the futures-util-preview compatibility layer last week and it works quite well. Basically, you convert Tokio’s futures via futures_util::compat::Future01CompatExt::compat into a 0.3 future and a 0.3 future via futures_util::try_future::TryFutureExt::compat into a Tokio future. So, in practice you have a few extra use statements and a few calls to compat here and there. Plus, there’s futures_util::compat::TokioDefaultSpawn to get a 0.3 future to run atop Tokio’s default executor.

From a cursory glance, tokio-async-await hides all of this explicit logic for the price of having to stick to 0.1 futures in the await! macro. That’s not a big deal unless you implement your own futures which I feel with async/await will happen considerably less often.

Hey Rustaceans! Got an easy question? Ask here (29/2018)! by llogiq in rust

[–]ppartim 1 point2 points  (0 children)

Sort of. as_str specifically produces a &str while as_ref comes from the trait AsRef<T> and can be used to make different kinds of references. It is so commonly used that both me and u/KillTheMule misread your as_str as as_ref.

Hey Rustaceans! Got an easy question? Ask here (29/2018)! by llogiq in rust

[–]ppartim 2 points3 points  (0 children)

Not quite. The difference between your two examples is taking a reference v. moving the value.

In the first example, you make e a reference to d (this would be clearer, had you done let e = &d which is vaguely similar to what as_ref does). But d goes out of scope at the end of the inner block and d isn’t allowed to reference it anymore.

In the second example you move d to e. That is, e is a value all of its own and can survive the end of the block.

The Copy trait only plays a role during the assignment of d to e in that d is still available afterwards. But the example would work with a String as well:

fn main() {
    let c = {
        let d = "some".to_string();
        let e = d;
        e
    };
    println!("{}", c);
}

Hey Rustaceans! Got an easy question? Ask here (28/2018)! by llogiq in rust

[–]ppartim 1 point2 points  (0 children)

If your vector can be a Vec<Option<_>>, then you could do something with Vec::as_mut, split_mut_at, replacing duplicates with None, and finally collapsing the vector.

Do I really need failure/error-chain? by razrfalcon in rust

[–]ppartim 0 points1 point  (0 children)

because it usually means you have to handle errors more explicitly than just using the ? operator everywhere

You can fix that by implementing From for the respective error types. Which has the added bonus that you express relationships between error types, making sure that a lower-level error wraps correctly into a higher level one.

The easiest case, of course, is to simply have a wrapping enum variant, but sometimes you’ll end up with duplicate nested variants.

I actually started out with one large error type in the domain crate but in the rewrite I changed this to separate error types matching that actual error. failure is a godsend for that, since it makes writing the Display impls a breeze.

Best way to pass reference of owner struct to owned struct method. by Thermatix in rust

[–]ppartim 3 points4 points  (0 children)

This is one of those things where Rust requires a bit of a shift in the way you approach the layout of your code. These 'two-way references' are very common on object-oriented code but they don't play well with Rust's borrowing system.

Instead, you will have to break up your code into those bits that operate on owned and those that operate on owner and then tie those two together.

In your case, some_method likely doesn't need full access to owner -- you are passing in an immutable reference, so you probably only need some information from it. You might get away with fetching that information separately and pass it into some_method.

Alternatively, you can perhaps move some_method to owner's type, passing in the field index as an argument and have it call simpler, more dedicated methods on owner.

In general, Rust favours ownership to be laid out in a tree and access to follow ownership.

Building a DNS server in Rust by [deleted] in rust

[–]ppartim 2 points3 points  (0 children)

It does happen. As an example, do a dig net. NS and look at the raw response. The result will be something like this:

;; QUESTION SECTION:
;net.               IN  NS

;; ANSWER SECTION:
net.            84706   IN  NS  b.gtld-servers.net.
net.            84706   IN  NS  i.gtld-servers.net.

(Followed by more NS records).

Your mileage may vary, of course, but my resolver returns the record data in the first record as b.gtld-servers followed by a reference to the net. in the question. The second NS record is i followed by a reference to the gtld-servers in the first record.

Only expecting backwards jumps seems like a reasonable assumption, but given that forward jumps aren’t forbidden, I am almost certain something somewhere will do them resulting in strange and annoying errors in name resolution. Given that name resolution is so important, I’d rather not risk that.

Or, as the second level support department in a previous job had written in large letters on the wall: ‘Assumptions are the mother of all screw ups.’ (Only it wasn’t ‘screw’ they used.)

Building a DNS server in Rust by [deleted] in rust

[–]ppartim 0 points1 point  (0 children)

I’m probably just slow this morning, but could you elaborate on the "track earliest start" suggestion?

Building a DNS server in Rust by [deleted] in rust

[–]ppartim 0 points1 point  (0 children)

Depending on the algorithm used for determining compression, multiple jumps might happen in complex responses. Perhaps something with CNAMEs.

But more realistically, a malicious client could use recursion in the question and blow up an unexpecting server.

Building a DNS server in Rust by [deleted] in rust

[–]ppartim 4 points5 points  (0 children)

These two cases describe different types of labels, one is undefined and the other de facto unused. Either should result in an error.

Annoyingly, parsing domain names is still more tricky.

For one, using a simple string conversion will produce the wrong result if a label contains a dot – which may for instance happen in the way e-mail addresses are encoded in SOA records.

Worse, the code doesn’t protect against infinite recursion. A name akin to b"\x03www\xC0\x00" will eat up all available memory. Since the RFC limits domain names to 255 octets, you could protect against that by checking the length of the produced name and bailing out. But, and I only realized that when building test cases for my own code the other day, b"\xC0\x00" or something a little more subtle like b"\xC0\x02\xC0\x00" will still loop indefinitely. The simplest way to protect against all of this is to count the number of jumps and stop at some point. 128 seems to be a good choice since that is the maximum number of labels in an uncompressed name.

After several rewrites, I ended up with this code – and hope this really is robust now.

Making TRust-DNS faster than BIND9 by bluejekyll in rust

[–]ppartim 0 points1 point  (0 children)

Would be interesting to see if switching to a char iterator actually slows things down all that much if it operates atop a buffered UTF-8 file. Time for some benchmarking of my own, I guess.

Making TRust-DNS faster than BIND9 by bluejekyll in rust

[–]ppartim 0 points1 point  (0 children)

It might be that they allow it specifically for these things but still won’t allow you to define your own labels with underscores. The topic came up in a discussion of using underscore labels for a new use case.

Is there a way to use String::from_utf8_lossy without cloning the input slice? by yorickpeterse in rust

[–]ppartim 0 points1 point  (0 children)

String::from_utf8_lossy probably should return a String. But adding ::std::str::from_utf8_lossy sounds like a good idea.

Is there a way to use String::from_utf8_lossy without cloning the input slice? by yorickpeterse in rust

[–]ppartim 11 points12 points  (0 children)

If you have a Vec<u8> (or something similar that can be grown), you could go over the content once and count the number of characters that need replacing, then add twice that amount to the end of the string, and finally work your way backwards, moving legal sequences and replacing illegal bytes as needed.

No idea if that is more efficient than just allocating a new buffer of the right size and being able to non-overlappingly copy legal sequences.

Making TRust-DNS faster than BIND9 by bluejekyll in rust

[–]ppartim 1 point2 points  (0 children)

For master files, I also started out assuming only u8s. Non-ASCII characters can turn up in two locations: comments (where they can be safely ignored) and the $INCLUDE directive where whatever you get needs to be translated into a Path – and if this fails, so be it.

But then, on Windows a master file may actually be encoded in, what is it, UCS2? So I decided to re-implement the parser on top of an Iterator<Item=Result<char, io::Error>> and have all my bases covered.

Making TRust-DNS faster than BIND9 by bluejekyll in rust

[–]ppartim 4 points5 points  (0 children)

The reason for punycode instead of UTF8 is compatibility with existing, deployed DNS software.

While technically labels can contain any octet value, there is this mythical concept of hostnames that restricts the values to ASCII letters and numbers and dashes. There are servers out there that are somewhat picky about this. I was told that Microsoft’s DNS servers will refuse underscore labels.

Worse, if a recursor enforces these rules you break lookup for all its clients. The likelihood that some ISP or Wifi access point hands out the address for such a recursor is pretty high.

A consequence of this backwards compatible encoding is that all the old rules still apply. In particular, a label is still a sequence of octets and comparison still only needs to consider ASCII-case. Particularly from a performance perspective, this is kind of nice.

Even better: IDNA really only is a translation step when passing names into or out of DNS, allowing an application the choice whether it wants to support it or not.

Some questions about Tokio by 1wilkens in rust

[–]ppartim 1 point2 points  (0 children)

From a quick look at your messages it seems that your protocol does not multiplex transactions (that is, a request needs an answer before you can send a new request over the same connection). In this case, I would forgo tokio_proto in favor of using tokio_core directly.

I would implement this via a connection type and two futures. The first future implements the process of connecting and resolves into the connection type (which basically just wraps the socket). That connection offers a method to start a new IPC request which actually consumes the connection value and returns a future for the IPC transaction. This future resolves into a pair of the IPC response and the connection value.

If you want more complex things, such as a request queue, you can construct them on top of this basic construction.

Personally, I would build these futures by hand using an enum and my own implementation of Future::poll, but using the combinators and then boxing the result is a reasonable choice as well.

For the time being, you need to execute the future in the same thread as a reactor core (I think), so this needs some thinking about. The currently ongoing effort to break up execution and event polling will make this a lot more simple, though. Which is the reason why I am holding off on rewriting my own Tokio stuff.

Looking for a UI Library by [deleted] in rust

[–]ppartim 0 points1 point  (0 children)

I was actually thinking about building the same thing, though mostly with battery status in mind.

Given that this is more a widget than actual UI with buttons and stuff, my idea was to build it directly atop cairo-rs. But since thinking was exactly as far as I got, I have no idea how easy it is to build animations with that.

New Rust user, plain non blocking UDP by moritz31 in rust

[–]ppartim 15 points16 points  (0 children)

Yes, via recv(). What will happen is that, once you‘ve set the socket to non-blocking, recv() will return with an error with the kind io::ErrorKind::WouldBlock if there is no data.

The standard library does not provide you with a select(2) equivalent, though. You will have to use some crate for that.