The function may not continue to exist in the form it has today. If we were to implement the suggestions in the above article, it would change. If we want to have tables for both f64 and f32, it may be better to convert it to a macro. And it would even not be unreasonable to just inline it in the calling code. Now the calling code supplies two functions to this one, and everything forces inlining. That for 10 shared lines of code...
If some user code want's to implement the ziggurat algorithm, I think they are better off writing it themselves. It is not the hardest part of writing a custom distribution. And then they can easily make it match details of their algorithm and tables, instead of forcing it in the same shape as out implementation happens to have.

@dhardy
If you are inclined to using marker trait and bundling functionality, then consider using a separate crate for traits only, something like rand-traits which will contain only trait definitions (thus it can be no_std capable without much hassle, or using your terminology being in core), which will be re-exported by rand. I think it would be acceptable solution, as traits will define only functionality without any implementations except default methods. Also it will allow to split RNGs into separate crates and re-export them in the rand if it will be deemed necessary.
You can see short draft of this idea here.

I also like the idea of a traits only core crate, because it lets a person focus on just a few moving parts at first.
We could also build various rand-utils stuff like I've been after, that only needs to know about the traits. It lets us have all the extra weird distribution stuff, picking from slices, picking from sets, picking from other strange collections like trees. The whole mess of functionality that's often easy enough to write, but prone to tiny off-by-one errors and things like that. Where it's better to have a well tested version in some library instead of a dozen versions cropping up in the wild.
If possible, hopefully our traits can stick to one or two required methods each (possibly with default methods as well), with sub-traits for extra required methods. We've mostly stuck to this so far and I think it's a path with good results.

Inspired by @newpavlov's code, I give you another variation. Actually, it's pretty much his code + fill/next implementations in terms of the other + example usage.
This could be the basis for a rand-traits crate. It's not as simple as just a CryptoRng trait, but impl_fill_from_u* and impl_next_u*_from_fill could be useful.

Nice! One small comment: I think it's worth to add default implementations to next_u32/u64/u128 based on private impl_uint_from_fill! and export only impl_fill_from_uint! utility macro, to make public API a bit smaller.

It may be better not to include any default implementations, so that the following mistakes aren't possible. But possibly this isn't so important.
struct MyRng { inner: SomeRng };
impl Rng for MyRng {
    fn next_u32(&mut self) { self.inner.next_u32() }
    // No next_u64() implementation! This will compile and *work*, but may be slower and generate different numbers!
}

@dhardy
I think your case will look like this:
impl Rng for MyRng {
    // `fill` is required method so it must be implemented
    fn fill(&mut self, dst: &mut [u8]) { impl_fill_from_uint!(self.next_u32, 4, dst); }
    fn next_u32(&mut self) { self.inner.next_u32() }
}

So next_u64 will be equivalent to two next_u32 calls and loop machinery in impl macro should be optimized out due to the use of fixed size array in the default next_u64 implementation, but ofc it's worth to check, as it could require inline annotations on methods to reliably work.

Call me crazy, but can't we have all of the methods default to another method, and then people can override whichever they want?
/// You must override at least one of these methods or you'll get a stack
/// overflow as soon as you use any of them. They default in terms of one
/// another in a loop, so that an override to any one of the methods here is
/// sufficient to give all of them a working implementation.
trait RandomGen {

    // this depends on next_u32
    // we could clearly also have a smarter error type i'm sure
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(),String> {
        for i in 0..(dest.len()) {
            // This is clearly not the fastest, it's just a demo
            dest[i] = self.next_u32() as u8;
        }
        Ok(())
    }

    // this depends on next_u64
    fn next_u32(&mut self) -> u32 {
        self.next_u64() as u32
    }

    // this depends on try_fill_bytes, which completes the loop
    fn next_u64(&mut self) -> u64 {
        unsafe {
            let mut bytes: [u8; 8] = std::mem::zeroed();
            self.try_fill_bytes(&mut bytes).unwrap();
            std::mem::transmute(bytes)
        }
    }
}

Then a RNG writer just has to write one method, whichever is easiest for their RNG to override.
If someone writes
impl RandomGen for MyGenerator {}

It will, as it says in the rustdoc, compile but stack overflow as soon as any of the RNG methods is called. I feel that this is a minor downside, because any amount of testing will instantly reveal that there's a problem.

@Lokathor
It's definitely possible, but  I think it could be a bit confusing for new users. Also why have you taken next_u32 for defining fill and not for example next_u64? (or how about next_usize? :) ) To exclude this bias I think it would be a fine solution to make fill method the only required one.

usize is hard to work with exactly because it's variable width. You have to have an extra step via conditional compilation every time you try to make a uX value to change into a usize value. It makes it very undesirable as a base type for RNG output. I say this from having tried to work with Haskell's RNG stuff several times, and always being frustrated that their core random interface uses what Rust would call isize as the output type. It's just bad.
The actual ordering of the loop is entirely unimportant as long as it's a full loop where each method depends on one other method, and is also depended on by one other method.
The reason that I don't like try_fill as the only required method that the others default in terms of is because I suspect (though can't confirm) that most generators will actually be oriented towards u32 or u64 outputs per generation step. So instead of being able to just define that and be done, they have to define that and then also define fill using a macro that just invokes the thing they actually wrote. So why not just write the looping version and do that work for them?
In terms of being potentially confusing, that's why you make clear docs. That's why even in the demo I made a rustdoc comment saying "this is how you use this". Other traits have a "this is how to implement this trait" section, no reason ours can't too.

I think usize represents a random index into an array, memory, etc., so you'd always want one chosen randomly from a Range<usize>, not a pure random one.  If you pull many random elements out of tables, then you should actually do this with u32 or smaller and cast to usize.

@Lokathor
I am fine with your suggestion. I guess it also removes the need for exposing utility macro(s). But I think:

We better use next_u64 for defining fill as it results in lesser number of calls, plus it's a word size on most of modern PCs.
It's better to define next_u32 in terms of fill, as implementers of CSRNGs will care less about next methods, thus it's more probable they'll forget to overwrite them, and it will result in twice slower performance for next_u32. While if we define next_u64 and code inlines it should have the same performance as self.next_u64() as u32.

So it results in something like this.

@burdges While you're correct that a usize is probably used as a way to index into a 1D collection, it still only is any number that's valid as an unsigned machine word (according to the local machine width). Thus, while you probably should not be using some theoretical next_usize() function, if such a function did exist it would only be correct if it could return values across the entire usize range. Obviously it'd be more useful to have something like next_index(usize length), but that's a whole other story.
@newpavlov Your example goes into a lot of details about a snappy default implementation for try_fill, but it misses the most important mark: it doesn't cause a dependency loop! As you have it here, if someone implements just next_u32 that won't let the others have a valid definition. You can have try_fill use next_u64 by default, but then next_u64 must use next_u32 by default, and next_u32 must use try_fill by default. Having fill at all complicates the system, though you could do it with that as well if we absolutely wanted that.
As to #[inline] or not, well, it might make some difference, but you should be using LTO if you want maximum speed anyway. Which makes means that you only need to worry about #[inline] for the sake of the speed of debug builds. We have to carefully weigh the compilation speed against the performance, because the point of debug builds is often to rebuild as fast as possible when iterating during development.

@Lokathor
Ah... you are right. I've updated my draft a bit, you can see it here.

Well, that's why try_fill should be in the loop, but fill should perhaps be a default method on an extension trait. If we're worrying about RNGs that "run out" somehow or otherwise error at all, then that might be the best way to do it.
The other option is to have entirely separate fallible RNG and infallible RNG. Assuming that there's at least one infallible CSPRNG implementation given, that might make the entire fallible set of RNGs into second-class citizens. Maybe they should be second class citizens like that though. After all, we should be preferring things that can't possibly fail whenever possible, I suppose.

For a bit of history of the rand crate:
I have written a basic changelog. And there are some notes about the design of rand on the old Rust wiki.

Thanks @pitdicker
@Lokathor @newpavlov we don't want next_usize(). Why? The only methods we want are fill/try_fill (because stream generators work with byte streams) and next_u32 / next_u64 (because there are native 32-bit and 64-bit generators). Algorithms need adapting when you switch word size, so we definitely don't wont a general next_usize; it wouldn't be reproducible across platforms.
We also don't want next_u64 defined in terms of fill. The only practical default IMO is the one currently in rand: ((self.next_u32() as u64) << 32) | (self.next_u32() as u64). (We could instead have @newpavlov's transmute trick, but it's an "optimisation" the compiler may be able to use anyway and unsafe.)
For those who didn't understand why my previous example could generate different results: consider a native 64-bit generator, directly implementing next_u64. In this case next_u32 simply does next_u64 as u32 (this is the current behaviour and anything else is probably slower). So the default impl of next_u64 in the wrapper would take half of two next_u64 results and combine them. Different results, and if you realise later, whoops you can't fix it without marking it a breaking change.

There are only three trait designs that seem to work well, after all the variants we've been through:

Completely separate Rng and CryptoRng traits. Implementations can support one or both. Wrapper types can support one via the other, if necessary. Example. This potentially misses one feature (optimal implementations of crypto PRNGs generating simple u32/u64 values), but this may not be a big deal.
A marker-only CryptoRng on top of RawRng; this requires the unstable never_type and is more complex, it seems unlikely to be accepted.
A marker-only CryptoRng on top of an unparameterised Rng; this requires either panic-only error handling (no Result) or multiple functions with mixed error styles.

(Any variant directly implementing one trait in terms of the other fails because (a) the impl conflicts with impl<R: Rng> Rng for &mut R type rules, and (b) prevents generators from directly supporting both traits.)
Of the above, I think the best options are either 1 (completely separate traits) or 3 (marker only trait with error handling via panic and catch_unwind).

Regarding your variants:

The big drawback here is that if RNG implements only CryptoRng it can not be used in the code which requires Rng. It can be circumvented by including wrapper type into rand over CryptoRng which will implement Rng in terms of fill. Also I think this variant should too utilize rand-traits crate.
Not a fan of using never_type
I think having next_u32 and fill as required methods should be enough, and try_fill, next_u64 and next_u128 with default implementation. I don't see much drawbacks in including try_fill, so I think it should stay.

Actually, the big advantage of this is that each trait can have exactly the methods it wants and implementations can support both directly if appropriate. So not a big problem.

Where does this come from? We talked about which methods are needed ages ago: fill, next_u32 and next_u64 at a minimum, next_u128 too makes some sense. Having both fill and try_fill is messy, but possible I suppose.

I took a little look at error handling in @briansmith's ring; as far as I can tell it just bubbles Result up anywhere an RNG gets used to pass on possible errors, but never gives any details (even though error::Unspecified can come from multiple sources). This seems somewhat messy; I still think using panic would be neater for rare errors.
The Rust Programming Language book actually has a section on when to use panic. It mentions there's no way to recover from a panic, but that's not true (see catch_unwind, also spawn). Panics are suggested for unrecoverable states, but overall Result looks a shade more appropriate.

The usize deal was more of a joke :P if you read again you'll see that no one was ever suggesting it that seriously.
The trouble with panic compared to Result is that Rust lets the compiler of the final program pick between unwind and abort. I think that if a library sets panic=unwind it can enforce that it won't compile into a binary with panic=abort set, but if we want to try and get some or all of this code into std then that's not acceptable to enforce panic=unwind. So, if we use panics, I think it would make it less attractive to have in std (maybe that's a low priority).
I would love to have 128-bit support, but since that's not stable yet last I checked it seems like we'd need to add it in a later version. We can add it as an additional default method at some point, and as implementations catch up they can choose to override as appropriate. I think that we should stick to Stable Rust only.

Given all this, I will re-iterate my support for a "completely separate" trait path. It leaves open the potential for a particular CryptoRng to forget to also impl Rng, but that's just an implementation detail thats leads to a quick and easy pull request. It's not any major drawback in the two-trait design.
BUT, if we have to settle on a single unified trait, I maintain that a simple loop between next_u32, next_u64, and try_fill will let one trait cover both the fallible and infallible cases at the same time, and would be the best of the unified options.

@dhardy @Lokathor

Actually, the big advantage of this is that each trait can have exactly the methods it wants and implementations can support both directly if appropriate. So not a big problem.

Given all this, I will re-iterate my support for a "completely separate" trait path. It leaves open the potential for a particular CryptoRng to forget to also impl Rng, but that's just an implementation detail thats leads to a quick and easy pull request. It's not any major drawback in the two-trait design.

I think it beats the purpose of splitting CryptoRng if CSRNG implementations will have to implement both of them for user convenience, or require usage of wrapper type, which will be quite unergonomic.
So I think the third variant is a better solution. How about this modification? Regarding cyclic dependencies vs required fill and next_u32, I am fine with both approaches, but the first will probably save boilerplate and will remove the need for utility macros in public API.

Where does this come from? We talked about which methods are needed ages ago: fill, next_u32 and next_u64 at a minimum, next_u128 too makes some sense. Having both fill and try_fill is messy, but possible I suppose.

I've lost you here... I've proposed exactly the same list with addition of try_fill, but just added what it's probably better to make fill and next_u32 required methods, instead of cyclic dependency proposed by @Lokathor.

I would love to have 128-bit support, but since that's not stable yet last I checked it seems like we'd need to add it in a later version.

It was suggested to add it through nightly-only feature disabled by default.

@burdges

Second, the OsRng "not ready yet" and "some fool deleted /dev/urandom" errors.

If I'm not mistaken, any API that allows checking for whether or not there's sufficient entropy also allows blocking until there is, so it should be possible to just block.

Yes 2^70 sounds big unless someone manages to seek around the stream somehow.

If someone manages to seek the stream in less time than it takes to just run the normal generator the same distance, then they've provided a counter-example to the PRNG being cryptographically secure. In other words, assuming that we're right that ChaCha is cryptographically-secure, this couldn't happen with ChaCha.

If someone manages to seek the stream in less time than it takes to just run the normal generator the same distance, then they've provided a counter-example to the PRNG being cryptographically secure. In other words, assuming that we're right that ChaCha is cryptographically-secure, this couldn't happen with ChaCha

ChaCha20 is seekable but also cryptographically secure. Going by the RFC 7539 a single 32-bit word of its state is reserved for a counter. By setting the counter to 1 and running the 20 rounds you get first set of random looking bytes. By setting it to 2 you get the second lot and so on. You don't need to give up seekability for cryptographic security. It might be a property that you look for in a CSPRNG, but it's not necessary.
The seekability is quite useful. Using SIMD you can generate 4 (or even 8) blocks in roughly the same time as it takes to generate single block of random bytes. No need to increase the state size either.

@joshlf we've already had some discussion of seekable RNGs, and it would be a useful feature to support. There's a proposed extension trait in the RFC, but possibly it should be renamed SeekableRng and have method fn seek_bytes(&mut self, offset: isize) instead.

The trouble with panic compared to Result is that Rust lets the compiler of the final program pick between unwind and abort.

I don't see the problem; if a program doesn't want to handle errors, so what? That said, I agree with your other points, except I would leave the default impls as now (fill_bytes via next_u64, next_u64 via next_u32, no default for next_u32) or remove.
Nice fill algorithm @newpavlov. I wrote another, but apparently forgot to push. (Reminder to self: benchmark)
Unfortunately your design for CryptoRng: Rng means that any CryptoRng which can fail needs to implement fill twice. But actually this isn't difficult, so maybe this is a good option.

If someone manages to seek the stream in less time than it takes to just run the normal generator the same distance, then they've provided a counter-example to the PRNG being cryptographically secure.

This is false.  ChaCha supports seeking, which rand exposes.

What should we do with ReadRng? Maybe we shouldn't expose it at all?

For use on a secure random stream (e.g. /dev/urandom), it is crypto-secure
Reading can fail, so try_fill is more appropriate than fill
Unless the underlying stream is reproducible there's no point worrying about endianness

For the specialised use by OsRng these points have obvious solutions, but "in general" it's less clear; it's also probably not very useful otherwise(?), so maybe we shouldn't export it at all.
On a similar vein, should our CryptoError support wrapping std::io::Error? Both ReadRng and getrandom can produce an io::Error which it might be useful to forward (there's no useful details that can be extracted as a &'static str, at least not via the Rust API).

I decided to use @newpavlov's fill_bytes algorithm. Benchmarks show significant improvement generating 1kB blocks:
Old algorithm:
test gen_bytes_chacha   ... bench:   2,645,789 ns/iter (+/- 25,644) = 387 MB/s
test gen_bytes_isaac    ... bench:   1,997,418 ns/iter (+/- 26,991) = 512 MB/s
test gen_bytes_isaac64  ... bench:   1,254,452 ns/iter (+/- 24,250) = 816 MB/s
test gen_bytes_xorshift ... bench:   1,019,526 ns/iter (+/- 29,957) = 1004 MB/s

My algorithm:
test gen_bytes_chacha   ... bench:   2,080,989 ns/iter (+/- 17,046) = 492 MB/s  127%
test gen_bytes_isaac    ... bench:   1,463,279 ns/iter (+/- 5,146) = 699 MB/s   136%
test gen_bytes_isaac64  ... bench:     778,342 ns/iter (+/- 8,233) = 1315 MB/s  161%
test gen_bytes_xorshift ... bench:     515,183 ns/iter (+/- 5,980) = 1987 MB/s  198%

@newpavlov's algorithm:
test gen_bytes_chacha   ... bench:   1,917,165 ns/iter (+/- 57,129) = 534 MB/s  138%
test gen_bytes_isaac    ... bench:   1,330,735 ns/iter (+/- 4,067) = 769 MB/s   150%
test gen_bytes_isaac64  ... bench:     462,346 ns/iter (+/- 1,399) = 2214 MB/s  271%
test gen_bytes_xorshift ... bench:     361,637 ns/iter (+/- 34,522) = 2831 MB/s 282%

The seekability is quite useful. Using SIMD you can generate 4 (or even 8) blocks in roughly the same time as it takes to generate single block of random bytes. No need to increase the state size either.

Isn't that an implementation detail of the PRNG? I don't see how that's an argument for providing a seeking interface for a CSPRNG. I don't think a seekable CSPRNG is generally useful and I'd rather not have to deal with any complications seekability adds.

I decided to use @newpavlov's fill_bytes algorithm. Benchmarks show significant improvement generating 1kB blocks:

Common key sizes for which CSPRNG size is important are 16 bytes, 32 bytes. If you do RSA blinding then 256/257 bytes and 384/385 bytes might be relevant. I would be suspicious of anything that needs a 1KB block. Apparently I'm not alone in thinking that since the BSD & Linux syscalls consider 256 bytes a reasonable cutoff.

Regarding error type, I am fine with the &'static str (perhaps with wrapper type?), but maybe @briansmith will have something to say about it.

Here I'm only talking about errors in CSPRNGs used for crypto purposes:
Let's say the PRNG fails. What kinds of failures are actually intereseting? Maybe "Not ready yet, but if you try again (after waiting) then maybe I'll work without any effort on your part." That would be better handled by providing separate non-blocking and blocking interfaces, rather than dealing with error types. Otherwise, I think if others are happy with a wrapper of &'static str, that would be fine with me, I think.

Isn't that an implementation detail of the PRNG? I don't see how that's an argument for providing a seeking interface for a CSPRNG. I don't think a seekable CSPRNG is generally useful and I'd rather not have to deal with any complications seekability adds.

Sorry, I wasn't masking argument for eekable CSPRNG. Was just saying that it's a very nice property that ChaCha has.

@dhardy
I think traits and their methods should be named more clearly to better convey their meaning, e.g. FromRng -> RngSeed(able) (otherwise it could be confusing as it collides a bit with std::convert::From), from_rng -> rng_seed, NewRng -> OsSeed(able), new -> os_seed.

I don't think a seekable CSPRNG is generally useful and I'd rather not have to deal with any complications seekability adds.

@briansmith Probably it's only got niche uses. I would probably have used seekability or multiple streams in the past had I known about such generators to allow reproducibility in multi-threaded sims. In any case, you don't have to "deal with any complications" unless you're implementing a PRNG and want to support seeking (for that reason, I think all the extension functionality should be in individual traits to enable a pick-what-you-want approach).

I would be suspicious of anything that needs a 1KB block. Apparently I'm not alone in thinking that since the BSD & Linux syscalls consider 256 bytes a reasonable cutoff.

It's a test; so what? I don't see any need for a cut-off; CSPRNGs are there explicitly to provide huge amounts of secure "random" data.
@newpavlov I don't like those names. We already have SeedableRng; from_rng could go there but possibly better to keep separate (so that from_rng can be supported without SeedableRng, and so that SeedableRng<X> and SeedableRng<Y> for seed types X, Y can both be supported); we could name the trait SeedableFromRng instead.
As for NewRng, it is there to provide a sensible default way to create a new instance, so it shouldn't have an obscure name (I don't want example code to keep using things like new_unseeded; that method shouldn't even exist).

The PractRand project has a very good overview of good-quality prngs. It even rates with a number of stars for quality, speed, theory, and list specific virtues. I think Rand should take a lesson from this, and only include the good-quality prngs. Also we can learn a thing or two for documentation.
http://pracrand.sourceforge.net/RNG_engines.txt
Included in the list of bad prng's is de XorShift family. Recommended for speed and pretty good quality are jsf32/64 and arbee

I am mostly done modifying ISAAC to ISAAC+. Just have to get the performance back to what it was before I started shuffling the code around :-). Also I have set up automated verification against the reference implementation. This is probably useful to add as some sort of the testing infrastructure to the rand crate...

I don't think I will merge any ISAAC+ modifications into my branch — instead, I think this should be implemented in a separate crate (maybe along with the existing ISAAC code), have some review(?), be adopted into rust-lang-nursery and only then possibly be used by default. Unfortunately there doesn't seem to be much literature on ISAAC+. So @pitdicker want to start a new rand-isaac or similar repo?
XorShiftRng should be removed, but having some fast RNG is useful for the benchmarks. We could maybe use pcg_rand instead, but the code size is huge (it's a large family of generators), so definitely not including the code in rand.
Any links for the jsf and sfc generators? Ah, I think this is jsf. Maybe we should add one or both of these as a replacement for XorShift.
It would be good to allow the higher cycle length for ChaCha mentioned here, I think.
(All RNGs are implemented in the RNG source code at least. Seems we have to deal with clunky zip files and lack of linking direct to code.)

The "minimal" PCGen version is one short function with one struct that holds two u64 values, 32-bit of output per step. It's fast, and we can support just the one short version and direct people to the full PCG family crate once things settle down.
/// The "minimal" PCG implementation. This is the simplest useful variant
/// from among the PCG family of generators.
///
/// See http://www.pcg-random.org/ for more.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct PCGen {
    /// The internal state of the generator.
    state: u64,

    /// The number stream of the generator.
    inc: u64,
}

impl PCGen {
    /// Produces the next 32 bits of random output. This changes the
    /// generator's internal `state` value, but not its `inc` value.
    pub fn step(&mut self) -> u32 {
        const TRANSITION_MAGIC_NUMBER: u64 =<PHONE_NUMBER>846793005;
        let oldstate = self.state;
        self.state = oldstate.wrapping_mul(TRANSITION_MAGIC_NUMBER).wrapping_add(self.inc|1);
        let xorshifted = (((oldstate >> 18) ^ oldstate) >> 27) as u32;
        let rot = (oldstate >> 59) as u32;
        let negated_rot = rot.wrapping_neg();
        xorshifted >> rot | (xorshifted << (negated_rot & 31))
    }
}

Then whatever traits we choose to layer on top.

I would be suspicious of anything that needs a 1KB block. Apparently I'm not alone in thinking that since the BSD & Linux syscalls consider 256 bytes a reasonable cutoff.

It's a test; so what? I don't see any need for a cut-off; CSPRNGs are there explicitly to provide huge amounts of secure "random" data.

I just mean that using a 1KB block isn't a realistic benchmark.

I'm not sure if anyone should take this seriously or not, but it is possible to report dynamic error details via struct Error(&'static str); by leaking memory. The leak should persist for the length of the program, but since it's small even a few thousand leaks shouldn't be a big issue (the playpen can handle one million recoveries, but not ten million).

This week I have dived in the Rands code for ISAAC, and tried to modify it to ISAAC+.
And now I think ISAAC+ is not such a good idea. Three reasons:

The paper proposing it contains errors and omissions.
No other mayor implementations.
The author of ISAAC claims the problem does not exist.

The paper proposing it contains errors and omissions
The ISAAC+ algorithm is described in the paper On the pseudo-random generator ISAAC by Jean-Philippe Aumasson.
However the specification is not complete and seems to contain errors.
The description of the original algorithm of ISAAC at page 2 misses a step. On line 5 it does not xor the result of f(a,i) with a.
This step is also missing from the description of the proposed ISAAC+. Should it be left out, or is this just a misprint?
The definition of the modified f'(a,i) is missing. But the text says that in that step we should "perform rotations instead of shifts, so as to get more diffusion from the state bits". So f'(a,i) is probably f(a,i) with shifts replaced by rotations.
It mentions two other changes: in the rngstep function one addition should be replaced by a XOR. And there should be one extra XOR with a.
Finally the algorithm in the paper shows that in the indirection function we should not do shifts, but rotations. But performing a rotation-right of 2 or 10 on an u32, and than only using the last 8 bits, is no different than a shift right. So this does nothing.
To finish the ISAAC+ algorithm is only given for the 32-bit variant, not for ISAAC-64. ISAAC-64 contains different constants, and one extra negation. Can we just apply the same modifications?
All in all, 4 errors or omissions in an algorithm described in about 14 lines, does not give a lot of confidence. Of course the modifications may have merit, but this does not paint a good picture.
No other mayor implementations
Of all the mayor implementations of ISAAC, none implement ISAAC+.
There is no reference implementation.
The only two implementations that I could find, seem to get it wrong.
This one in Crystal misses an xor with a on line 56.
Another one also does not do rotations on the state bits.
The author of ISAAC claims the problem does not exist
In his paper mr. Aumasson presents 4 sets of weak states. If I read it right, there can be weak states with a bias in the first two rounds, e.g. the first 8192 bytes. The author of ISAAC, Robert Jenkins, refutes the claim (at the bottom of this section about a predecessor, IA).
It seems his argument is: if you define a few subsets of the entire set of possible states, no wonder you are going to end up with subsets with a bias. The bias exists because you defined it. The entire set is unbiased.
This should all not be a problem if you can not deduce the rng is in such a weak state. You can only know it if the state was badly initialized, or if it is possible to deduce from the produced random numbers. The initialization routine created by Robert Jenkins (and used in Rand) should take care of the first requirement. Especially if it is seeded by an OS RNG. And deducing from the produced random numbers would mean ISAAC was broken.
Conclusion: I am no expert, and may have gotten some details wrong. But I have somewhat lost my faith in ISAAC+, and think Rand should not implement it.

Thanks for the thorough work @pitdicker! Sounds like a good argument to me.
BTW: major not mayor

Trying to answer questions related to the trait designs, I optimised fill_bytes for the ChaCha and Isaac generators, then switched functions to return a Result and benchmarked. On my machine (Haswell CPU, 64-bit Linux):

making fill_bytes return a Result has no observable performance impact in benchmarks and was fairly easy to implement
making the next_* functions return a Result had no observable performance impact in most benchmarks and a small impact in a few; it wasn't so nice to implement (unwrap in many places)

Of course, this is with no real handling (unwrap in some places, unhandled result warning in others), and I have no idea how this scales to other architectures. Please test for yourself (rng-result branch vs master; see commit notes).

Related but separate from the above, I note that buffered CSPRNGs like ChaCha and Isaac should implement at least one of next_* and also fill_bytes for optimal performance. This means that it's not a big deal if fill_bytes has different error handling from next_*.
Based on this, I think the best approach may be to have the following functions in Rng and CryptoRng (except the latter might omit next_*). (The main reason for not returning a Result in the next_* functions may simply be to avoid unwrap everywhere; performance may of course differ on other platforms. Having infallible fill_bytes as well is probably pointless.)
fn next_u32(&mut self) -> u32;
fn next_u64(&mut self) -> u64;
fn try_fill(&mut self, dest: &mut [u8]) -> Result<(), Error>;

Neat. I will try to benchmark this when I get a chance.
Just clone the repos and then cargo bench?

Uh, cargo bench won't work without nightly. Additionally, it tries to build all tests but some aren't fixed in the experimental branch, so select individual benchmarks with the --bench option.

It did some reading up about small non-cryptographic random number generators, and thought to share the results. Sorry in advance for the long post :-). Maybe it can help forming an informed opinion about which RNGs to include.
Criteria for implementing a RNG.
Generation of pseudorandom numbers has been an interesting area of computer science, with many advances over the years. It has also been approached from a practical side with extremely large (and slow) statistical tests. This means there currently exist very high quality RNGs. We should choose which RNGs to recommend or implement in Rust not just on what is currently used much, but set a minimum quality bar.
Things to look for are:

it should be the best variant of a family.
it should not (or almost not) fail the statistical tests TestU01 and PractRand.
it should not be trivially predictable.
it should offer some unique features, to merit its use beside other RNGs.
its should be fixed (e.g. not change in the future)
a period of at least 2^60

I only look here at non-cryptographic RNGs, because the cryptographic ones have completely different considerations. They have much more underlying theory and are on order of magnitude slower.
Conclusion of generators to include (or: my opinion):

vectorised truncted xorshift64/32*
PCG XSH RR 64/32 (MCG) and possibly a variant that returns 64-bit results
ISAAC
maybe PCG RXS M XS 32 and PCG RXS M XS 64

Destinctive features
Vectorised truncted xorshift64/32*:

very, very fast
generates random numbers (almost) one at a time, not a whole block at once
seekable

PCG:

very fast
generates random numbers one at a time, not a whole block at once
seekable
multiple streams
extension with a larger state, to offer a larger period,
k-dimensional equidistribution

ISAAC:

strongest non-cryptographic generator
reasonably fast

PCG RXS M XS 32 and PCG RXS M XS 64:

generates every 32 or 64-bit number exactly once
very fast

Xorshift
Xorshift is a family of pseudorandom number generators designed by George Marsaglia, a renowned figure in the world of random number generation. They are among the fastest random number generators, requiring very small code and state.
Xorshift itself is a generator with well-known statistical weaknesses. That is why it is usually combined with step that improves the numbers it generates. The different versions are:

xorshift: the base algorithm.
xorshift+: add together two numbers generated with base xorshift.
xorshift*: multiply the result of xorshift with a constant.
truncated xorshift*: multiply the result of xorshift with a constant and truncate the lower half the the result.

Truncated xorshift* is the best variant available. It offers excellent statistical qualities. And truncating the result gives it a useful quality: it is not like all other variants are trivially predictable. Otherwise once you know as many result as te size of the state (typically 1~256), you can calculate all the future results. With a truncated result, is is not impossible, but far from trivial.
A second aspect to note is that the different xorshift algorithms can choose the size of the state they operate on. Some operate on a state no larger than the result they generate. Others go up to 1024 bits. The larger the state, the larger the period is before the RNG repeats itself. A state of 32 bits translates in the case of xorshift to a period of 2^32-1. This means in practice that no more than 4gb of random numbers can be generated before repeating, which is an amount some applications can reasonably consume.
So for an xorshift variant to be generally usable, we require it to have a state of at least 64 bits. Especially when the generator is going to be used in multiple processes or with jump-ahead, we may even require 128 bits to be future-proof.
Note that using a very large state, like 1024 bits, can be used as a way to improve the statistical qualities of an otherwise weak algorithm, like xorshift1024+. On the PCG blog this is called 'to big to fail'. And it is a good solution to have a fast generator with a resonable quality.
Currently rand implements Xorshift128, which is statistically weak, easily predictable, but has a large period and is very fast.
What I would like to propose is to implement truncated xorshift64/32*. This has the following advantages:

pretty fast (but not as fast as plain xorshift)
the xorshift family is well-recognized (to worded nicely: it has excellent heritage)
not trivially predictable
excellent statistical qualities
a state of 64 bits is ok for most uses

To improve its performance, I propose we run it four times in parallel (e.g. use SIMD). This has the disadvantage of increasing the state 4-fold and adding a counter (resulting in a total of 36 bytes). The period increases to 2^66 (a small improvement). But the speed should at least double.
One potential advantage of the xorshift family is that it can support jump-ahead.
A variant we can also consider part of the xorshift family, is xoroshiro128+. It describes itself as the successor to xorshift128+. It is indeed faster and of better statistical quality than xorshift128+. But it really falls short of truncated xorshift*. Creating some hybrid thing like truncated xoroshire 128/64* could be a thing, but not something we should try.
PCG (permuted congruential generator)
PCG is the latest and best variant in a long line of LCGs, linear congruential generators. LCG's are among the oldest and best-known pseudorandom number generator algorithms. The theory behind them is relatively easy to understand, and they are easily implemented and fast.
LCGs have well-known statistical weaknesses. PCG improves upon them by applying the result of an LCG with a permutation step that improves its statistical qualities. Also it usually does not return the full state, but only half. Thus making the next result not trivially predictable.
PCG offers many variants, and many features. One of the choices is between a permutation step with 'random rotation' (RR) and with 'random shift' (RS). RR is statistically slightly better than RS, but slightly slower. I propose we go with RR, as the performance difference is minimal.
Another variant is the choice of base generator: LCG or MCG. The difference is a single addition. They offer the same quality, but the MCG has a four times smaller period than LCG. We should choose the MCG variant, because the difference in period is small. If a period of 2^62 is not going to cut it, a period of 2^64 is probably neither good enough.
Finally there is the choice between a generator that returns all of its result, or a truncated portion. As with truncated xorshift*, a truncated result makes the next result not trivially predicatable. But a generator that guarantees to return every number exactly once, can have its uses.
So we should implement PCG XSH RR 64/32 (MCG). Random rotation in the permutation step, the slightly faster MCG base generator, and truncating the result from 64 to 32 bits.
Also useful could be PCG XSH RR 128/64 (MCG). The advantage is that it directly generates 64-bit numbers, and has a very large period (2^126). The problem is that it operates on 128-bit integers. I am unsure if we can implement it with good performance by emulating u128 with u64, or should depend on nightly features for the best performance.
Just like with ISAAC, we can implement both and advertise them as 32-bit and 64-bit variants.
For 32-bit architectures the 32-bit variant should be the fastest. Offering two variants of a generator, and picking the one that fits the target architecture best, is recommended by PractRand. So we could offer Pcg32Rng, Pcg64Rng, and PcgWordRng.
PCG offers a number of other features that could be useful to implement:

seekability (e.g. jump-ahead, jump-back),
multiple streams,
extension with a larger state, to offer a larger period (would depend on allocations, or making its struct a DST),
k-dimensional equidistribution (as long as you choose a state big enough, any random sequence will eventually turn up, like an archive with Shakespeare's Hamlet).

Potentially useful could be the PCG variants that generate every number exactly once: PCG RXS M XS 32 for u32, PCG RXS M XS 64 for u64, and PCG XSL RR RR 128 (slightly different, because multiplication of 128-bit integers is expensive).
ISAAC
ISAAC is a well-known random number generator in a line of array based RNGs. The first was RC4, which is known to have weaknesses. Robert Jenkins designed IA, IBAA and finally ISAAC that improve upon it.
It is designed as cryptographically secure, but is not founded in cryptographic theory. So while it should not be used for cryptographic purposes, it is the strongest non-cryptograpic RNG. And that while still being reasonably fast.
One of the problems with ISAAC is that its quality depends on the quality of its initial seed. And the initial seed must be very large, 1024 bits for the 32-bit variant, and 2048 bits for the 64-bit variant.
One feature we could offer is making the size of the state variable. I think with a state of 256 bits it could still be very strong (something to test). The C code supports tweaking the constants, but is rarely if ever done (although PractRand mentions it). It could make initialisation faster, and maybe the smaller state helps a little with performance. But it would make it depend on allocations, or make its struct a DST.
ISAAC exists in two variants, ISAAC and ISAAC64. The one that is best to choose depends on the target architecture, and whether you need u32 or u64 as results.
A disadvantage of ISAAC that it does not generate a new number every time you need one, but generates numbers in blocks of 256. So its performance cost is not constant. It is not impossible to modify the algorithm to generate a new number only when you need it, but this would at least halve the performance.
As mentioned above there is a proposed ISAAC+ variant, but it may not be a neccecary improvement. The only description of it is also not complete.
Other small generators
PractRand mentions a number of other small good RNGS:
A small noncryptographic PRNG by Robert Jenkins
It has a state of 128 bits, and a period of about 2^126. It passes all statistical tests so far.
It is a good small fast chaotic RNG and it is better studied that other small fast chaotic RNGs.
This small fast RNG has an advantage over most in that a lot of people have looked at it, and many people have tried their own custom unpublished RNG tests on it.  No biases have been reported in the ouput of the 32 or 64 bit versions of this.
A big problem is that this algorithm can end up in a state that cycles. So a good implementation should recognize when such a state occurs, and prevent it (or require reseeding). Currently there are six cycles of length 1 known, and for greater cycle lengths they are unknown. So checking for them is not really possible. Although the chance of ending up in a state that cycles is small, I therefore suggest we should not implement it.
SFC (Small Fast Counting RNG, version 4)
SFC is designed by the author of the PractRand library.
He describes it as: "This algorithm is has a combination of very fast speed, good statistical properties, small size, and (on larger word sizes) guaranteed minimum cycle length. This has not been as thoroughly tested as the jsf algorithm, but on my tests so far it appears superior to jsf in both quality and speed. It's basically a good small chaotic RNG driven by a bad smaller linear RNG. The combination gives it the strengths of each - good chaotic behavior, but enough structure to avoid short cycles.
One problem of this RNG is that its implementation is not fixed. This is version 4, and it may change / improve in the future. I think it is best to give it some more time to mature or get used / studied more before we implement it.
XSM*
This one is also designed by Chris Doty-Humphrey, the author of PractRand. XSM* is designed because at the time there was no other decent random access RNG (like LCG).
"The underlying state transition function is a simple linear 64 bit (for xsm32) or 128 bit (for xsm64) LCG with very poor constants (to maximize speed). The poor quality of the state transition function is made up for by a relatively complex non-linear output function. It looks like the state transition function ought to be too poor to be completely fixed by the output function, and like the the statespace expansion trick ought to produce excessively correlated states, but I have not managed to find any such issues in practice."
This description does not give me a lot of faith, and PCG bassically fits all the use cases of XSM*.
Again a disclaimer: I am no expert.

I'd like to note that there is a pcg_rand crate that has PCG stuff in pure rust already (that is, not bindings to C or anything). I'm not sure of the current code completeness, but we might be able to get @robojeb to merge their crate in with rand directly, if we want to stuff it all into one crate, or have a group of crates under a rust-rand project, or something like that. I expect that non-rand generators already have rust versions as well, and we can also reach out to the others once we know what we're wanting to put in.

@Lokathor Id be willing to work with someone to merge in the PCG rand stuff.
Currently I have been experimenting with two forms of the library, a macro_based version which generates implementations of all the component parts, and a fully generic version which uses a lot of trait bounds (both can be found in the history of the repository)
There were some limitations on the fully generic version because of the lack of associated constants, which caused me to have an excessive number of function calls and prevented some constant optimizations. I haven't had time since the associated constants were merged to retry to the other version of the system.
As for the state of the code, it is currently nearly feature complete, there are the following features:

Multiple Multiplier, Stream, and Output Mixins (provided by the C++ implementation) which can be dynamically mixed together using generics.
Ultra large generators using the extension method described in the paper.
One simple non-generic implementation for code reference.

The library is currently missing

More output mixins.
Arbitrary jump-ahead via quick exponentiation (I have been dragging my feet on this one because most other rust generators don't expose this interface)

@dhardy Your os.rs / mod imp section for windows needs a use CryptoError; in it. Other than that my results are the same as yours: the rand-result branch and the master branch have nearly identical run times.
@robojeb I'm not sure we need every possibly PCG flavor. That's really overwhelming to folks who come to the docs and want to know what to use. Part of our task would be to pick one or two defaults and offer those up as "you should pick either of these unless you really know you want something else". Probably the best PCG with 32-bit output and the best PCG with 64-bits of output. For whatever definition of best we want to come up with. I think since they'd be in the "non-crypto" section of the crate, favoring a little extra towards speed over other elements would be warranted, as long as the other categories aren't skimped on.

Nice write-up @pitdicker.
It could also be interesting to look at Efiix, though really it needs more review by crypto-experts (I can't find any published articles on it).
I would definitely rather go with multiple small-ish crates implementing a few RNGs each than one big crate. That way, any RNGs which fall out of fashion, are implemented for esoteric or historical use only, or are simply not wanted for a specific use case don't need to be included in build paths.

About the CryptoRng concept: if this is meant to signify "crypto" RNGs, what should that mean in practice? (Lets assume for the moment that this semantic meaning is the only difference between CryptoRng and plain Rng.)

Have strong requirements on what is allowed to implement CryptoRng: e.g. only allow for well reviewed and tested implementations of well studied algorithms. But then (a) many implementations of RNGs will not implement this trait even though they are supposed to be secure and (b) where a CryptoRng is required, there won't be many implementations available (and maybe not any user-space PRNGs for a long time). For practical reasons users may only require an Rng, or it may become common to wrap RNGs with something like as_fake_crng. (Of course, third party libraries can still implement CryptoRng for any old trash, because no one polices such things.)
CryptoRng only implies the intention that the internal state be hard to guess from output. This rules out very weak RNGs (e.g. MT) but is inclusive enough to include RNGs with minimal security but not really intended for cryptography. On the other hand, this might be enough for things like the std::collections::hashmap where an attacker is unlikely to see the output directly anyway, and the worst an attacker could do is DoS? (Legitimate question: I have no background in cryptography.)
Somewhere in between, regarding intention and burden-of-proof

My thoughts on this are:

For any crypto where an attacker could achieve more than DoS or even where DoS would be easy, users should still be advised to use OsRng, or if necessary a well-reviewed crypto RNG (maybe ChaCha). CryptoRng doesn't really come into this.
For various other uses, it is desirable for an RNG to have minimal cryptographic strength: e.g. this should be enough to ensure seeding one PRNG from another does not accidentally create a clone (if it did, this internal state was trivially recovered from output — but that's what crypto-RNGs should prevent), and probably this is good enough for most uses of randomised hash functions (?). For this, a trait like CryptoRng might be useful.

Thus my thoughts are that if a marker trait of cryptographic strength is going to be useful at all, it is on the weaker, more permissive end. (E.g. this would let FromRng restrict seeding to hard-to-guess RNGs, preventing accidental cloning.) Of course, if we go in this direction, CryptoRng is not an appropriate name (but HardToGuessRng is too long...).
We could even have two marker traits for different levels of "crypto strength"... ultimately though I'm pessimistic about any "strong crypto requirements" marker trait achieving much other than confusion and a mess of workarounds.

There are always explicit names like RngStdSafe, meaning safe for usages in std like HashMap under some conventional threat model, or RngNonDoS if you want to be more specific.

@dhardy I think our best bet may be to use one of the precise mathematical definitions of a CSPRNG that are available (e.g., https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Definitions). This is going to be trickier for us than for other languages for whom there's no trait, but only a reference to the OS-provided RNG (e.g., Go's crypto/rng package simply says, "Package rand implements a cryptographically secure pseudorandom number generator," which is mathematically imprecise, but that's OK for them because they further clarify exactly which PRNG is used - getrandom syscall on Linux or /dev/urandom if getrandom isn't available, etc).

So I've thought about this some more, and I think we should go with the standard mathematical definition (as outlined in that wikipedia article). It doesn't provide any of the fanciness of some more stringent definitions (e.g., forward secrecy, which allows for a CSPRNG's previous outputs to remain secure even if a future internal state is leaked), but it should be sufficient provided that the algorithm it's being used in truly only relies on the CSPRNG property and doesn't accidentally rely on some other specialized behavior.

@joshlf this definition would be fine if it were easy to prove or disprove. But for many generators, there is neither proof nor disproof available. E.g. ISAAC has had a $1000 prize on offer for 21 years for a method of recovering a key from some given output (not quite the same thing since it doesn't account for bias, but the generator is supposed to be unbiased).

We now have a Gitter chat page. I certainly won't be there all the time myself but it may have its uses.
Due to travel and other commitments I will have little time for "rand" stuff this week and probably no time the next two weeks (leading up to RustFest Zürich, which I will be attending). I will try to get a new RFC regarding the core traits out this week; hopefully that can get merged soon as the first step towards implementation.

@joshlf this definition would be fine if it were easy to prove or disprove. But for many generators, there is neither proof nor disproof available. E.g. ISAAC has had a $1000 prize on offer for 21 years for a method of recovering a key from some given output (not quite the same thing since it doesn't account for bias, but the generator is supposed to be unbiased).

Unfortunately there's no proof or disproof in this space. Even the SHA-256-based CSPRNG implemented in the Linux kernel is only a true CSPRNG on the (unproven) assumption that SHA-256 is itself a collision-resistant hash function. However, it is believed by most cryptographers to be secure in this manner, and that's about as good as we get for these things. There are CSPRNGs whose security is proven under much simpler and foundational assumptions, but they are very slow and not used in practical systems.

@dhardy
Regarding NewRng as I understand it will be implemented only for SeedableRngs, right? And OsRng and other RNGs which do not require user seeding will use traitless new() method or Default trait?
SeedableFromRng sounds not bad, but I feel it's a bit redundant. How many examples of RNGs we have which would like to support several seed types not covered by as conversions between unsigned integers? One common pattern could be seeding RNG from &[u8], but it's probably can be covered by additional method in the NewRng. (but it could require restricting seed types somehow) So to sum up: I think we can add seeding from RNG to SeedableRng trait which will have seed as associated type.

Having infallible fill_bytes as well is probably pointless.
Based on the above, the best trait design is probably to put the three above functions into Rng, and have CryptoRng: Rng with no additional functions (marker trait only).

Sounds good to me! But I am not sure about removal of infallible fill, if we take a look at Rust std we'll see a lot of infallible methods which can panic and their try_* counterparts.
About CryptoRng meaning, I think in the trait documentation it's better to go with "implementations of well studied algorithms" which were designed as CSRNGs. But we can't possibly forbid crate authors to implement CryptoRng for insecure RNGs, so it's more about signaling intentions "this RNG is suitable for cryptography" and "this algorithm requires CSRNG".
Regarding chicken and egg problem, I don't think it's a serious problem. Most applications will just use OsRng and other crates will implement CryptoRng if they'll want to be compatible with modern rand.

The rand-core RFC is now written.
I'll proof-read then open the RFC PR; only comment on typos/major gaps/etc. here please.
@newpavlov I added your suggestion for SeedableRng but am not really a fan.

A big plus for the new section 'Default implementations of functions'.
I was just thinking in the same direction.
Suppose you have an algorithm that produces u64. If the algorithm is fast, the fastest way to get an u32 is to truncate the result. But for a slower algorithm like ISAAC it may be better to do some tricks with the array that holds the results.
If the algorithm produces u32, the given method to combine two results in an u64 may not be the fastest. I just wrote something custom while trying to optimize Xorshift.
So picking a default like next_u32 and offering the rest to have default implementations in terms of that, is really a hit or miss depending on what type the algorithm outputs.
Requiring implementations to provide them, with implementations ready to include, is a very good solution.

I think the documentation should  contain an example of making a wrapper Rng type to remind people not to do anything silly.  And many menton why default implementations do not exist.  Alternatively, there could be a macro impl_wrapper_rng!(x) to produce the fns for wrapper Rng types, where x is normally self.0 or whatever.

Isn't an fn easier than the NewSeeded trait?  I think folks will remember foo easier if they write both foo::<>() and  use rand::foo as opposed to use rand::AnotherName;.  And type inference works better.  I'd think your NewSeeded trait is not object safe anyways.
#[cfg(feature="std")]
pub fn rng_from_os<R: SeedFromRng>() -> io::Result<R>
    let mut r = OsRng::new()?;
    Self::from_rng(&mut r)
}

Thanks for the feedback. This is the type of thing I was hoping to put in a new comment thread however; never mind.
@pitdicker glad we think alike on that. The existing RNG impls were definitely not entirely optimal; I didn't thoroughly test my example implementations. Good point about next_u32 not necessarily wanting to truncate, though ISAAC is pretty fast so it may still be the best option for that one? Less so if we had a 64-bit ChaCha (if that's even practical to implement on modern CPUs).
@burdges I was trying to stay away from macros simply because of the #[macro_use] requirement and the pending macro overhaul. The impl_wrapper_rng!(MyRng) thing might work but probably is tricky because of the macro hygiene stuff; please make a PR if you come up with something (I don't have the time). Same goes for your documentation suggestion; a PR would be great.
Bummer, I have next_u128 everywhere in the example implementation but not mentioned in the RFC IIRC. It's kind of a pain with the #cfg stuff, especially for testing, but it's there because if we don't have a default implementation then adding it later wouldn't be backwards compatible.

I see.  In fact, I suppose NewSeeded can be overridden with specialization too.

Just another thought on error handling here: https://github.com/rust-lang/rfcs/issues/2191

I'm requesting that rand::sample() be fallible in this issue: rust-lang-nursery/rand#194

I did miss a lot of comments but I couldn't parse a conclusion from the rfc text.
Did we reach a consensus regarding providing only opaque RNGs (std_rng, weak_rng, thread_rng, osrng,....) (stable across major versions)?

Not really. There's some discussion here. There has also been quite a bit of talk about reproducible generators; these would obviously require names (e.g. ChaChaRng) but there's no hard requirement these are kept in the rand crate.

Thanks. IMHO we shouldn't expose anything named. StdRng and WeakRng can be seedable/reproducible anyway.

You can always guarantee they're stable across major versions.

Isn't that what I just said above? But why? We've already got a proposal to replace StdRng with a better generator.
Unless you mean allow breakage. But again why? Someone writes a scientific simulator, does an experiment, publishes a result, along with a link to let other people reproduce output. Someone else writes a game with procedurally generated maps. Symmetric encryption works the same way: permute using a fixed pseudo-random sequence (although obviously people select named CSPRNGs for that, like ChaCha20). Queue a major version update, and suddenly people have trouble reproducing the simulation result and players complain that their maps changed, and for no good reason. Reproducibility means guaranteeing to produce the same output.

I'm not sure were we are misunderstanding each other but let's try again. I wholeheartedly agree that reproducibility is important, so let's get that out of the way.
I'm arguing that rand shouldn't provide specific implementations say like xoroshiro or chacha, specially because the optimal choice tend to change over time for various reasons. Users will be able to achieve reproducibility using the provided opaque generators as long as they're continue using the same major version 1.X, 2.X, ...


Fix: Broken Slack notification

Signed-off-by: Kunal Verma<EMAIL_ADDRESS>Description
Fixing the broken slack notification, which is triggered when someone stars this repo!

Notes for Reviewers
Signed commits

[X] Yes, I signed my commits.

Hey @leecalcote , does this do the trick or need some more improvements?


Over The Air Flickering Evasion Attack

Description
This pull request continues from #1077 to add final changes to integrate the new attack
Fixes #881
Type of change
Please check all relevant options.

[ ] Improvement (non-breaking)
[ ] Bug fix (non-breaking)
[x] New feature (non-breaking)
[ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
[ ] This change requires a documentation update

Codecov Report

Merging #1102 (6e547bb) into dev_1.7.0 (80476fc) will decrease coverage by 22.73%.
The diff coverage is 0.00%.

@@              Coverage Diff               @@
##           dev_1.7.0    #1102       +/-   ##
==============================================
- Coverage      65.05%   42.31%   -22.74%
==============================================
  Files            221      222        +1
  Lines          19274    19354       +80
  Branches        3527     3530        +3
==============================================
- Hits           12539     8190     -4349
- Misses          5318    10200     +4882
+ Partials        1417      964      -453

Impacted Files
Coverage Δ

art/attacks/evasion/over_the_air_flickering.py
0.00% <0.00%> (ø)

...rt/defences/detector/poison/clustering_analyzer.py
8.22% <0.00%> (-89.25%)
:arrow_down:

...ces/detector/evasion/subsetscanning/scanningops.py
11.59% <0.00%> (-85.51%)
:arrow_down:

art/attacks/evasion/carlini.py
8.40% <0.00%> (-80.87%)
:arrow_down:

...ient_descent/projected_gradient_descent_pytorch.py
16.27% <0.00%> (-76.75%)
:arrow_down:

art/metrics/verification_decisions_trees.py
13.68% <0.00%> (-73.16%)
:arrow_down:

art/attacks/evasion/decision_tree_attack.py
22.66% <0.00%> (-69.34%)
:arrow_down:

art/attacks/evasion/adversarial_patch/utils.py
11.53% <0.00%> (-69.24%)
:arrow_down:

art/attacks/evasion/elastic_net.py
17.41% <0.00%> (-69.04%)
:arrow_down:

art/defences/detector/poison/activation_defence.py
15.71% <0.00%> (-68.90%)
:arrow_down:

... and 76 more

@minhitbk Thank you very much for your great review! I'm merging according to our offline discussion.


mitmproxy: 8.1.1 -> 9.0.1

Description of changes

Things done

Built on platform(s)

[ ] x86_64-linux
[ ] aarch64-linux
[ ] x86_64-darwin
[ ] aarch64-darwin

[ ] For non-Linux: Is sandbox = true set in nix.conf? (See Nix manual)
[ ] Tested, as applicable:

NixOS test(s) (look inside nixos/tests)
and/or package tests
or, for functions and "core" functionality, tests in lib/tests or pkgs/test
made sure NixOS tests are linked to the relevant packages

[ ] Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
[ ] Tested basic functionality of all binary files (usually in ./result/bin/)
23.05 Release Notes (or backporting 22.11 Release notes)

[ ] (Package updates) Added a release notes entry if the change is major or breaking
[ ] (Module updates) Added a release notes entry if the change is significant
[ ] (Module addition) Added a release notes entry if adding a new NixOS module
[ ] (Release notes changes) Ran nixos/doc/manual/md-to-db.sh to update generated release notes

[ ] Fits CONTRIBUTING.md.

Fails to run for me
[nix-shell:~/.cache/nixpkgs-review/pr-205027]$ ./results/mitmproxy/bin/mitmproxy --help
Traceback (most recent call last):
  File "/nix/store/j5b7j8ph4gn7r7qizrvws86nkg3965rk-python3.10-mitmproxy-9.0.1/bin/.mitmproxy-wrapped", line 6, in <module>
    from mitmproxy.tools.main import mitmproxy
  File "/nix/store/ss9rcik1klipl4dby23aanfxi74aikx4-python3.9-mitmproxy-9.0.1/lib/python3.9/site-packages/mitmproxy/tools/main.py", line 9, in <module>
    from mitmproxy import exceptions, master
  File "/nix/store/ss9rcik1klipl4dby23aanfxi74aikx4-python3.9-mitmproxy-9.0.1/lib/python3.9/site-packages/mitmproxy/master.py", line 7, in <module>
    from mitmproxy import eventsequence
  File "/nix/store/ss9rcik1klipl4dby23aanfxi74aikx4-python3.9-mitmproxy-9.0.1/lib/python3.9/site-packages/mitmproxy/eventsequence.py", line 6, in <module>
    from mitmproxy import http
  File "/nix/store/ss9rcik1klipl4dby23aanfxi74aikx4-python3.9-mitmproxy-9.0.1/lib/python3.9/site-packages/mitmproxy/http.py", line 26, in <module>
    from mitmproxy.net import encoding
  File "/nix/store/ss9rcik1klipl4dby23aanfxi74aikx4-python3.9-mitmproxy-9.0.1/lib/python3.9/site-packages/mitmproxy/net/encoding.py", line 13, in <module>
    import zstandard as zstd
  File "/nix/store/lg2l85kqb1x9i9by2g4mjya3d4rpn21l-python3.9-zstandard-0.19.0/lib/python3.9/site-packages/zstandard/__init__.py", line 39, in <module>
    from .backend_c import *  # type: ignore
ModuleNotFoundError: No module named 'zstandard.backend_c'

Running python programs from nixpkgs-review is sometimes broken like in this case. works when running outside.


Refactoring Profile tests; DRY Approach

One of the cool things I learned with Jeffrey Way at Laracasts is to use the setUp method for repetitive object factory.

Wow!
I didn't know about the * @dataProvider toggableNotifications that is really good!


Refactor BaseName into PIDName + determine naming conventions

BaseName is implementing a rudimentary version of PIDName, these can be refactored into a class with optional fields to cover relevant data.
existing data:

Name (species name, institute name, etc)
registry (name where was information acquired from)
registry abbreviation (short name, or acronym)
reference ID (for species code, institute number, registryID etc)

Does anyone know how utilizing a custom class works with our Field(...,) values?
for instance, PIDName inheriting BaseName to some degree like:
class PIDName(AindModel):
"""Model for associate a name with a persistent identifier (PID) and the registry for that PID"""
name: str = Field(..., title="Name")

becomes:
class PIDName(AindModel):
"""Model for associate a name with a persistent identifier (PID) and the registry for that PID"""
name: BaseName = Field(..., title="Name","Attribute") <-- you can see here that labeling for fields gets weird with this inheritance

would something work like:
`class Institution(Enum, metaclass=BaseNameEnumMeta):
"""Institution name"""
AIBS = PIDName(name=BaseName(name="Allen Institute for Brain Science", abbreviation="AIBS"), registry="ROR", registry_identifier="xxx")
AIND = PIDName(name=BaseName(name="Allen Institute for Neural Dynamics", abbreviation="AIND"), registry="ROR", registry_identifier="yyy")

`
I'm guessing we'd have to add PIDName to the metaclass at the top? I don't actually know about that part. @dyf does this make sense?

(also, the formatting on that got wonky - I'm not good with formatting on here)

I think if that works, we don't need to refactor BaseName or PIDName, just use them together

@saskiad I think this would work for instantiating a variable, but specifically with the Field(...,[content]) im not sure how i would handle things. Ie,
name: BaseName(name,abbreviation) = Field(..., title="Name, abbreviation")

Maybe there is a way for me to utilize field twice, for one variable?

@mae the Enums are defining PIDName instances, so I think what @saskiad said is correct.

@saskiad I think this would work for instantiating a variable, but specifically with the Field(...,[content]) im not sure how i would handle things. Ie, name: BaseName(name,abbreviation) = Field(..., title="Name, abbreviation")

So I don't know that you need to define a new field here, I think it's just using the BaseName when you make the enum list


Fix parquet statistics for ListingTable and Utf8View with schema_force_string_view, rename config option to schema_force_view_types

Which issue does this PR close?
Closes #12123
Rationale for this change
On write: parquet file written with utf8/large-utf & binary/large-binary schema (so is in metadata).
On read: we would like to be able to read as the more performant view types.
Previous work has already used the schema_force_string_view to read into utf8view and binaryview, by passing around a bool to the ParquetOpener.
This work is to focused on getting the parquet statistics, on read, to properly compute when reading as view types.
What changes are included in this PR?

move the schema_force_string_view up a few lines, to be with the "read" (not write) config options.
remove the passing around of bools

this was done by merging table_schema (with views) and file_schema (without views)

add tests which run with true|false for schema_force_string_view

~There are two tests marked as incomplete: an expected panic and a commented out test. Both tests will successfully pass once the next (anticipated) arrow release occurs. In order to prove this, there is a PoC over here which branches of the in-progress WIP for the arrow upgrade and then adds the commits from this PR.~. I merged in the latest main with the arrow-rs release (thank you!) and those tests are now passing.
Are these changes tested?
Yes.
Are there any user-facing changes?
No.

Thanks again @wiedld


Cannot read property '0' of undefined

Modelio v3.8 introduces a bug when dealing with bidirectional Many-to-Many relationships (the error when JHipster UML parses the XMI is Cannot read property '0' of undefined)

In the official documentation of jhipster UML it is explained that there is a bug with Modelio 3.5.x in the generation of bidirectional Many-to-Many relationships and that it will be fixed for version 6. As it turns out, I am using version 3.8 and even persite the problem
jhipster-uml .\dallay.xmi

Parser detected: MODELIO.

An error has occurred:
        TypeError
Error message:
        Cannot read property '0' of undefined
Stack trace:
TypeError: Cannot read property '0' of undefined
    at addAssociation (C:\Users\Acosta\AppData\Local\Yarn\Data\global\node_modules\jhipster-uml\lib\editors\modelio_parser.js:161:38)
    at fillAssociations (C:\Users\Acosta\AppData\Local\Yarn\Data\global\node_modules\jhipster-uml\lib\editors\modelio_parser.js:155:5)
    at Object.parse (C:\Users\Acosta\AppData\Local\Yarn\Data\global\node_modules\jhipster-uml\lib\editors\modelio_parser.js:28:3)
    at Object.<anonymous> (C:\Users\Acosta\AppData\Local\Yarn\Data\global\node_modules\jhipster-uml\lib\jhipsteruml.js:54:25)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
    at Module.load (internal/modules/cjs/loader.js:599:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
    at Function.Module._load (internal/modules/cjs/loader.js:530:3)
    at Module.require (internal/modules/cjs/loader.js:637:17)

Reproduce the error

This is the model
image
xmi
The XMI file

image
xmi
Versions

JHipster
JHipster UML
Editor & version

5.8.2
2.0.3
Modelio 3.8

[ ] Checking this box is mandatory (this is just to show you read everything)

The only workaround I found was to downgrade or upgrade to a more stable version. Can you do it?

hey, i aslo meet this error, and my jhipster's version is 5.7.1, jhipster uml's version is 2.0.3, and modelio is 3.8.
this is my xmi


Dependency upgrades

Coverage: 93.713%. Remained the same when pulling 326fab97bfd44cfb282f585588e9212f4be38b07 on cody-dep-upgrades-2023-01-05 into 2327fd0b1d19a2e1312c598b45d9eee77b3b16e6 on main.


Replaced service binding with service key

Context
Service binding is causing interruption in database connection after deployment as new service binding replaces old.
Changes proposed in this pull request
Replacing with service key that defines a persistent set of credentials.
https://trello.com/c/MplZ2Jqd/3539-pginsufficientprivilege-error-permission-denied-for
Guidance to review
Ensure database connection still works in review app
Important business

Does this PR introduce any PII fields that need to be overwritten or deleted in db/scripts/sanitise.sql?
Does this PR change the database schema? If so, have you updated the config/analytics.yml file and considered whether you need to send 'import_entity' events?

 PG::InsufficientPrivilege: ERROR: permission denied for


feat: update svgr/webpack loader

This PR replaces svgr/webpack loader with its latest version available in @svgr/webpack package.
The change solves https://github.com/facebook/create-react-app/issues/4798.
I tested this code change locally and it now reads custom config from i.e. .svgorc.json file (placed in the project root directory).

Upgrading to SVGR 2 should reduce dependency size. It is a major including a lot of breaking changes (especially the support of runtime configurations). That's why I think upgrading it before releasing create-react-app 2.0 is very important.

This is waiting on https://github.com/smooth-code/svgr/issues/179

Also, we need to disable prettier.

See #5062, thanks for your contribution @kopacki! I'll be sure to mention you in the release notes. 😄

There is one more thing. SVGR latest requires the latest version of JSDOM, but it could work with the previous one. We should check if bundle size is not impacted by two versions of JSDOM (one for Jest and one for SVGR).

Neat, @neoziro! Thanks for the update.
It'd be really neat if the packages handling configuration, optimizing, and prettifying svgs could be decoupled from the main package so we're not bloating the dependency tree.

@Timer I think it is already decoupled enough, "@svgr/core", "@svgr/cli", <EMAIL_ADDRESS>I will not decouple it more.


Update MD file on new branch 2017-17-10_18-11-39

:warning: Validation status: warnings

File
Status
Preview URL
Details

split/ref.yml
:warning:Warning

Details

split/updateTestRef.md
:white_check_mark:Succeeded

split/ref.yml

[Warning] Uid(Microsoft.SqlServer.Server) has already been defined in ref1.yml.
Line 1: [Warning] Invalid file link:(~/content.md).

For more details, please refer to the build report.
Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report.


Restructure and improve the docs

Supersede #675 opening the PR in the main repo to (hopefully) get the Cloudflare preview.

cc. @kanatohodets please feel free to review the new structure.
On top of this, either you look for gaps yourself(there are for sure) or, I would go for the examples: https://github.com/dylibso/chicory/issues/667
For TinyGo I think this PR is the best "getting started".


CAS 5.0 RC4 snapshot Hazelcast deprecated properties

CAS 5.0 RC4 snapshot
Centos 7, openJdk 1.8.0, Tomcat 8.5.6
During tomcat start.
catalina.out
2016-10-17 08:08:49,942 WARN [com.hazelcast.config.MapConfig] - <As of version 3.7, `minEvictionCheckMillis` and `evictionPercentage` are deprecated due to the eviction mechanism change. New eviction mechanism uses a probabilistic algorithm based on sampling. Please see documentation for further details>

cas.properties
# hazelcast ticket cache replication
cas.ticket.registry.hazelcast.pageSize=500
cas.ticket.registry.hazelcast.mapName=tickets
cas.ticket.registry.hazelcast.cluster.evictionPolicy=LRU
cas.ticket.registry.hazelcast.cluster.maxNoHeartbeatSeconds=300
cas.ticket.registry.hazelcast.cluster.multicastEnabled=false
cas.ticket.registry.hazelcast.cluster.evictionPercentage=10
cas.ticket.registry.hazelcast.cluster.tcpipEnabled=true
cas.ticket.registry.hazelcast.cluster.members=<IP_ADDRESS>,<IP_ADDRESS>,<IP_ADDRESS>
cas.ticket.registry.hazelcast.cluster.loggingType=slf4j
cas.ticket.registry.hazelcast.cluster.instanceName=localhost
cas.ticket.registry.hazelcast.cluster.port=5701
cas.ticket.registry.hazelcast.cluster.portAutoIncrement=true
cas.ticket.registry.hazelcast.cluster.maxHeapSizePercentage=85
cas.ticket.registry.hazelcast.cluster.backupCount=1
cas.ticket.registry.hazelcast.cluster.asyncBackupCount=0
cas.ticket.registry.hazelcast.cluster.maxSizePolicy=USED_HEAP_PERCENTAGE
cas.ticket.registry.hazelcast.cluster.timeout=5
# cas.ticket.registry.hazelcast.crypto.signing.key=
# cas.ticket.registry.hazelcast.crypto.signing.keySize=512
# cas.ticket.registry.hazelcast.crypto.encryption.key=
# cas.ticket.registry.hazelcast.crypto.encryption.keySize=16
# cas.ticket.registry.hazelcast.crypto.alg=AES

log4j2.xml
       <AsyncLogger name="com.hazelcast" level="info" additivity="false">
            <AppenderRef ref="casConsole"/>
            <AppenderRef ref="casFile"/>

First, thanks very much.
Second, please use backticks such as ``` to format settings, etc in code blocks. Makes it easier for everyone to read.

Solved in the new 5.1 SNAPSHOT


go.dev: proxy images referenced from overview tab to protect user privacy

The overview page links directly to images referenced from the readme markdown.  These references allow third parties to track users on pkg.go.dev.
Github proxies images referenced to from the readme to prevent such tracking.  See the following for more information:

https://github.blog/2014-01-28-proxying-user-images/
https://help.github.com/en/github/authenticating-to-github/about-anonymized-image-urls

pkg.go.dev should do the same.
What is the URL of the page with the issue?
https://pkg.go.dev/github.com/labstack/echo?tab=overview and many other ?tab=overview pages.
What did you do?
I visited the page.
What did you expect to see?
I expected to see requests to pkg.go.dev and it's trusted partners.
What did you see instead?
I saw image requests to sourcegraph.com, img.sheilds.go and goreportcard.com.

/cc @julieqiu per owners.


Add System.Runtime.GetRandom

Close #2062 .
Need to wait until neo-project/neo#2541 resolves.
Testing:

[x] make env_up works and accepts blocks.
[ ] test bench in mixed setup.

So have you tested in mixed consensus setup?

@roman-khimov yes, works as expected https://github.com/nspcc-dev/neo-bench/tree/rc3-update, will make a PR in bench after merge.


New option: initial and maximum buffer size

At the commit d4cb247, it allows modifying initialSize of internal buffer.
https://github.com/kawanet/msgpack-lite/blob/d4cb247/lib/encoder.js#L15
function Encoder(initialSize,output) {

The change was once reverted by the reason mentioned at issue #6 however.
At the commit d00df50, it gives constant MIN_BUFFER_SIZE and MAX_BUFFER_SIZE instead.
-var BUFFER_LENGTH = 2048;
+var MIN_BUFFER_SIZE = 2048;
+var MAX_BUFFER_SIZE = 65536;

Some application may know the best size of the internal buffers.

Proposal:
var encoder = createEncodeStream({initialBufferSize: 2048, maxBufferSize: 65536});

Naming:

initialBufferSize and maxBufferSize ?
minBufferSize and maxBufferSize ?
initial and maximum ?
initial and limit ?

Note: https://github.com/nodejs/node-v0.x-archive/blob/master/lib/buffer.js#L83

Node.js's Buffer class allocates 8KB buffer pool per default.
If application requests a smaller buffer which is equal or less than 4KB, it gives a snippet from the pool.
If application requests a larger buffer which is larger than 4KB, it gives a dedicated buffer newly allocated.

It seems it's not needed.


Add UMLs for reserve command

Add class diagram and sequence diagram for reserve command

Codecov Report

Merging #210 (c8725bd) into master (3921d16) will not change coverage.
The diff coverage is n/a.

@@            Coverage Diff            @@
##             master     #210   +/-   ##
=========================================
  Coverage     78.78%   78.78%
  Complexity     1346     1346
=========================================
  Files           167      167
  Lines          3860     3860
  Branches        515      515
=========================================
  Hits           3041     3041
  Misses          673      673
  Partials        146      146

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3921d16...c8725bd. Read the comment docs.


fix move_and_slide_with_snap cause artifact

close #31097

When near the slope, applying snap may cause object intersect with the slope, so just cancel it in this case.

Conflicts with changes I just merged from #30588.
@Demiu Maybe you can help review this PR as you also modified this code recently?

I rebased locally and confirmed that it fixes #31097.
I hoped it might fix #24874 too, but it seems not.

This definitely seems to not do what it should
if (p_stop_on_slope && col.travel.cross(p_floor_direction) == Vector3(0, 0, 0))
col.travel is the result of a move_and_collide along the snap vector. In 99% of use cases this == will almost always be true, as most people will use snap vector that's parallel to the p_floor_direction, so a cross will almost always return a zero vector, and if it does snapping doesn't occur.  Or very close to it, due to move_and_collides pre un-stucking code, which is when we would NOT want to apply that motion as it would move us sideways. Thus this basically disables snapping for the most popular use case of it. Unless I missed something I think is completely wrong and just breaks snapping. This is from a mathematical point of view, programmatically this == will almost always be false no matter what because floats and this is an == instead of is_equal_approx. This applies both to 2d and 3d.
It seems the issue with #31097 isn't the application of col.travel itself (because for 2d the snap movement was already limited to be perpendicular to floor plane:
col.travel = p_floor_direction * p_floor_direction.dot(col.travel);
I might be wrong about this but it seems the real problem is that what KinematicBody2D::move_and_collide considers to be "snapped to the floor" doesn't align with what the KinematicBody2D::separate_raycast_shapes considers to be "not intersecting with anything". So move_and_collide moves the body "down" and then separate_raycast_shapes separates it from the ground by moving it perpendicular to the floor (not the floor vector) which is a little up and to the side for a slope. Rinse, repeat and you're slowly moving down a slope. At least I think

@raphael10241024 Is this still desired? If so, it needs to be rebased on the latest master branch.


Allow users to add a customized toolbar

Mantis 1.1.0 is released with a CustomizedCropToolbar conform to CropToolbarProtocol in the example project.

@guoyingtao Looks good, thank you so much! The only thing I noticed is thathandleCropViewDidBecomeUnResettable() is not getting called after having called cropToolbarDelegate?.didSelectedReset().
(And all these didSelected... functions should probably be called didSelect….

@mschonvogel You are right. I will fix them in the next release.

@mschonvogel I released Mantis 1.1.1. I add delegate?.cropViewDidBecomeUnResettable(self) to the reset() function in CropView.swift. That way every time the status is reset, the handleCropViewDidBecomeUnResettable() of CropToolbar will be called.

Ok, thathandleCropViewDidBecomeUnResettable is getting called now.
function naming is still wrong: didSelecte remove the e 😜

You are right 😂 Will fix it.

I fixed this issue in Mantis 1.2.0.

Awesome


get_events() doesn't have any effect

Bug description
Using get_events() as mentioned in documentation (https://google-calendar-simple-api.readthedocs.io/en/latest/events.html#list-events), get_events() doesn't have any effect.
With the code below exactly the same events as without a call of get_events() are returned, also outside the defined start and end dates.
To Reproduce
Steps to reproduce the behavior:

Installed the latest version with pip install gcsa
execute code below

Code used:
import datetime

from gcsa.event import Event
from gcsa.google_calendar import GoogleCalendar
from gcsa.recurrence import Recurrence, DAILY, SU, SA

from beautiful_date import Jan, Apr

calendar =<EMAIL_ADDRESS>
calendar.get_events(start_date=datetime.date(2023, 1, 1),
                    end_date=datetime.date(2023, 12, 31),
                    single_events=True,
                    order_by='startTime')

for event in calendar:
    print(event)

Error or unexpected output
Events far outside the start and end are displayed.
Tech:

OS: MacOS
GCSA version: 2.1.0
Python version: 3.11.1

Additional context
None

Hi, thank you for the issue submission.
.get_events() returns the iterable of events. Just iterate over it:
events = calendar.get_events(start_date=datetime.date(2023, 1, 1),
                    end_date=datetime.date(2023, 12, 31),
                    single_events=True,
                    order_by='startTime')

for event in events:
    print(event)

I'll think about clarifying the documentation on this. I'll close the issue. If you have any questions, feel free to ask them here, in GitHub Discussions, or on discord.

Thats what I did too, but using your code results in an error:
  File "/Users/mstuebner/PycharmProjects/google_calendar/.venv/lib/python3.11/site-packages/googleapiclient/discovery.py", line 1048, in method
    raise TypeError("Got an unexpected keyword argument {}".format(name))
TypeError: Got an unexpected keyword argument start_date

Right, didn't notice that issue. The correct arguments' names are time_min and time_max:
events = calendar.get_events(time_min=datetime.date(2023, 1, 1),
                    time_max=datetime.date(2023, 12, 31),
                    single_events=True,
                    order_by='startTime')

for event in events:
    print(event)

confirmed working, thanks.