/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use serde::Serialize; use std::{
io::{self, Write},
num::NonZeroUsize,
};
/// A quantity of items that can fit into a payload, accounting for /// serialization, encryption, and Base64-encoding overhead. pubenum Fit { /// All items can fit into the payload.
All,
/// Some, but not all, items can fit into the payload without /// exceeding the maximum payload size.
Some(NonZeroUsize),
/// The maximum payload size is too small to hold any items.
None,
/// The serialized size of the items couldn't be determined because of /// a serialization error.
Err(serde_json::Error),
}
impl Fit { /// If `self` is [`Fit::Some`], returns the number of items that can fit /// into the payload without exceeding its maximum size. Otherwise, /// returns `None`. #[inline] pubfn as_some(&self) -> Option<NonZeroUsize> { matchself {
Fit::Some(count) => Some(*count),
_ => None,
}
}
}
/// A writer that counts the number of bytes it's asked to write, and discards /// the data. Used to compute the serialized size of an item. #[derive(Clone, Copy, Default)] struct ByteCountWriter(usize);
/// Returns the size of the given value, in bytes, when serialized to JSON. pubfn compute_serialized_size<T: Serialize + ?Sized>(value: &T) -> serde_json::Result<usize> { letmut w = ByteCountWriter::default();
serde_json::to_writer(&mut w, value)?;
Ok(w.count())
}
/// Calculates the maximum number of items that can fit within /// `max_payload_size` when serialized to JSON. pubfn try_fit_items<T: Serialize>(items: &[T], max_payload_size: usize) -> Fit { let size = match compute_serialized_size(&items) {
Ok(size) => size,
Err(e) => return Fit::Err(e),
}; // See bug 535326 comment 8 for an explanation of the estimation let max_serialized_size = match ((max_payload_size / 4) * 3).checked_sub(1500) {
Some(max_serialized_size) => max_serialized_size,
None => return Fit::None,
}; if size > max_serialized_size { // Estimate a little more than the direct fraction to maximize packing letmut cutoff = (items.len() * max_serialized_size - 1) / size + 1; // Keep dropping off the last entry until the data fits. while cutoff > 0 { let size = match compute_serialized_size(&items[..cutoff]) {
Ok(size) => size,
Err(e) => return Fit::Err(e),
}; if size <= max_serialized_size { break;
}
cutoff -= 1;
} match NonZeroUsize::new(cutoff) {
Some(count) => Fit::Some(count),
None => Fit::None,
}
} else {
Fit::All
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.