mirror of
https://github.com/nushell/nushell.git
synced 2025-04-01 11:46:20 +02:00
enable streaming in random
binary
/chars
(#15361)
# User-Facing Changes - `random binary` and `random chars` now stream, reducing memory usage and allowing interruption with ctrl-c
This commit is contained in:
parent
dd56c813f9
commit
3fe355c4a6
@ -1,5 +1,5 @@
|
||||
use super::byte_stream::{random_byte_stream, RandomDistribution};
|
||||
use nu_engine::command_prelude::*;
|
||||
use rand::{thread_rng, RngCore};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RandomBinary;
|
||||
@ -57,12 +57,12 @@ impl Command for RandomBinary {
|
||||
}),
|
||||
}?;
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let mut out = vec![0u8; length];
|
||||
rng.fill_bytes(&mut out);
|
||||
|
||||
Ok(Value::binary(out, call.head).into_pipeline_data())
|
||||
Ok(random_byte_stream(
|
||||
RandomDistribution::Binary,
|
||||
length,
|
||||
call.head,
|
||||
engine_state.signals().clone(),
|
||||
))
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
|
49
crates/nu-command/src/random/byte_stream.rs
Normal file
49
crates/nu-command/src/random/byte_stream.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::Signals;
|
||||
use rand::{
|
||||
distributions::{Alphanumeric, Standard},
|
||||
thread_rng, Rng,
|
||||
};
|
||||
|
||||
pub(super) enum RandomDistribution {
|
||||
Binary,
|
||||
Alphanumeric,
|
||||
}
|
||||
|
||||
pub(super) fn random_byte_stream(
|
||||
distribution: RandomDistribution,
|
||||
length: usize,
|
||||
span: Span,
|
||||
signals: Signals,
|
||||
) -> PipelineData {
|
||||
let stream_type = match distribution {
|
||||
RandomDistribution::Binary => ByteStreamType::Binary,
|
||||
RandomDistribution::Alphanumeric => ByteStreamType::String,
|
||||
};
|
||||
|
||||
const OUTPUT_CHUNK_SIZE: usize = 8192;
|
||||
let mut remaining_bytes = length;
|
||||
PipelineData::ByteStream(
|
||||
ByteStream::from_fn(span, signals.clone(), stream_type, move |out| {
|
||||
if remaining_bytes == 0 || signals.interrupted() {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let bytes_to_write = std::cmp::min(remaining_bytes, OUTPUT_CHUNK_SIZE);
|
||||
|
||||
let rng = thread_rng();
|
||||
let byte_iter: Box<dyn Iterator<Item = u8>> = match distribution {
|
||||
RandomDistribution::Binary => Box::new(rng.sample_iter(Standard)),
|
||||
RandomDistribution::Alphanumeric => Box::new(rng.sample_iter(Alphanumeric)),
|
||||
};
|
||||
out.extend(byte_iter.take(bytes_to_write));
|
||||
|
||||
remaining_bytes -= bytes_to_write;
|
||||
|
||||
Ok(true)
|
||||
})
|
||||
.with_known_size(Some(length as u64)),
|
||||
None,
|
||||
)
|
||||
.with_span(span)
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
use super::byte_stream::{random_byte_stream, RandomDistribution};
|
||||
use nu_engine::command_prelude::*;
|
||||
use rand::{
|
||||
distributions::{Alphanumeric, Distribution},
|
||||
thread_rng,
|
||||
};
|
||||
|
||||
const DEFAULT_CHARS_LENGTH: usize = 25;
|
||||
|
||||
@ -71,7 +68,6 @@ fn chars(
|
||||
stack: &mut Stack,
|
||||
call: &Call,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let span = call.head;
|
||||
let length: Option<Value> = call.get_flag(engine_state, stack, "length")?;
|
||||
let length = if let Some(length_val) = length {
|
||||
match length_val {
|
||||
@ -97,17 +93,11 @@ fn chars(
|
||||
DEFAULT_CHARS_LENGTH
|
||||
};
|
||||
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let random_string = Alphanumeric
|
||||
.sample_iter(&mut rng)
|
||||
.take(length)
|
||||
.map(char::from)
|
||||
.collect::<String>();
|
||||
|
||||
Ok(PipelineData::Value(
|
||||
Value::string(random_string, span),
|
||||
None,
|
||||
Ok(random_byte_stream(
|
||||
RandomDistribution::Alphanumeric,
|
||||
length,
|
||||
call.head,
|
||||
engine_state.signals().clone(),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
mod binary;
|
||||
mod bool;
|
||||
mod byte_stream;
|
||||
mod chars;
|
||||
mod dice;
|
||||
mod float;
|
||||
|
Loading…
Reference in New Issue
Block a user