From da10101295f6c21c92e78b77c3c1f643d4e434ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 18 May 2026 10:57:55 +0000 Subject: [PATCH 1/6] Initial plan From 183c9e5beba008b5892b2c8039b4656e2c486348 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 18 May 2026 11:02:52 +0000 Subject: [PATCH 2/6] perf(huff0): cache encoded weight descriptions on HuffmanTable Agent-Logs-Url: https://github.com/structured-world/structured-zstd/sessions/6bdb0283-45b1-4909-8dde-e9b2114fbf4c Co-authored-by: polaz <4152123+polaz@users.noreply.github.com> --- zstd/src/huff0/huff0_encoder.rs | 60 +++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/zstd/src/huff0/huff0_encoder.rs b/zstd/src/huff0/huff0_encoder.rs index 1070ccd4..334e44fd 100644 --- a/zstd/src/huff0/huff0_encoder.rs +++ b/zstd/src/huff0/huff0_encoder.rs @@ -1,4 +1,5 @@ use alloc::vec::Vec; +use core::cell::OnceCell; use core::cmp::Ordering; use crate::{ @@ -109,12 +110,12 @@ impl>> HuffmanEncoder<'_, '_, V> { } fn write_table(&mut self) { - let weights = self.weights(); - let weights = &weights[..weights.len() - 1]; // don't encode last weight - if let Some(fse_description) = Self::encode_weight_description(weights) { + if let Some(fse_description) = self.table.cached_encoded_weight_description() { self.writer.write_bits(fse_description.len() as u8, 8); - self.writer.append_bytes(&fse_description); + self.writer.append_bytes(fse_description); } else { + let weights = self.weights(); + let weights = &weights[..weights.len() - 1]; // don't encode last weight Self::write_raw_weight_description(self.writer, weights); } } @@ -210,6 +211,7 @@ impl>> HuffmanEncoder<'_, '_, V> { pub struct HuffmanTable { /// Index is the symbol, values are the bitstring in the lower bits of the u32 and the amount of bits in the u8 codes: Vec<(u32, u8)>, + cached_encoded_weight_description: OnceCell>>, } impl HuffmanTable { @@ -313,14 +315,12 @@ impl HuffmanTable { /// Returns exact writable table-description size when representable. pub(crate) fn try_table_description_size(&self) -> Option { - let weights = self.weights(); - let weights = &weights[..weights.len() - 1]; - if let Some(fse_description) = HuffmanEncoder::>::encode_weight_description(weights) - { + if let Some(fse_description) = self.cached_encoded_weight_description() { return Some(fse_description.len() + 1); } - if weights.len() <= 128 { - Some(weights.len().div_ceil(2) + 1) + let raw_weights_len = self.codes.len().saturating_sub(1); + if raw_weights_len <= 128 { + Some(raw_weights_len.div_ceil(2) + 1) } else { None } @@ -340,6 +340,16 @@ impl HuffmanTable { .collect::>() } + fn cached_encoded_weight_description(&self) -> Option<&[u8]> { + self.cached_encoded_weight_description + .get_or_init(|| { + let weights = self.weights(); + let weights = &weights[..weights.len() - 1]; + HuffmanEncoder::>::encode_weight_description(weights) + }) + .as_deref() + } + /// Estimates encoded payload size in bytes directly from per-symbol counts. pub(crate) fn estimate_compressed_size_from_counts(&self, counts: &[usize]) -> usize { let bits = self @@ -364,6 +374,7 @@ impl HuffmanTable { let table_log = highest_bit_set(weight_sum) - 1; let mut table = HuffmanTable { codes: alloc::vec![(0, 0); weights.len()], + cached_encoded_weight_description: OnceCell::new(), }; let mut nb_per_rank = [0u16; 13]; for &weight in weights { @@ -1236,6 +1247,35 @@ fn large_alphabet_weight_description_uses_fse_when_raw_is_unrepresentable() { )); } +#[test] +fn cached_encoded_weight_description_is_reused_for_write_table() { + let mut data = Vec::new(); + for symbol in 0u8..=255 { + data.extend(core::iter::repeat_n(symbol, usize::from(symbol) + 1)); + } + let table = HuffmanTable::build_from_data(&data); + let desc_size = table + .writeable_table_description_size() + .expect("table description must be writable"); + let cached = table + .cached_encoded_weight_description + .get() + .and_then(Option::as_ref) + .expect("large alphabet fixture must cache FSE description") + .clone(); + assert_eq!(desc_size, cached.len() + 1); + + let mut encoded = Vec::new(); + { + let mut writer = BitWriter::from(&mut encoded); + let mut encoder = HuffmanEncoder::new(&table, &mut writer); + encoder.write_table(); + writer.flush(); + } + assert_eq!(encoded[0] as usize, cached.len()); + assert_eq!(&encoded[1..], cached.as_slice()); +} + #[test] fn encoded_weight_description_is_accepted_by_donor_huf_reader() { use zstd::zstd_safe::zstd_sys; From 15e9417cba621ba86600140b1db802ff517f8ad8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 18 May 2026 12:11:40 +0000 Subject: [PATCH 3/6] perf(huff0): avoid duplicate raw-weight recompute in write_table fallback Agent-Logs-Url: https://github.com/structured-world/structured-zstd/sessions/29cef8e6-3ed8-4ed3-a365-84f0ebf18546 Co-authored-by: polaz <4152123+polaz@users.noreply.github.com> --- zstd/src/huff0/huff0_encoder.rs | 71 +++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/zstd/src/huff0/huff0_encoder.rs b/zstd/src/huff0/huff0_encoder.rs index 334e44fd..cb01a574 100644 --- a/zstd/src/huff0/huff0_encoder.rs +++ b/zstd/src/huff0/huff0_encoder.rs @@ -110,12 +110,27 @@ impl>> HuffmanEncoder<'_, '_, V> { } fn write_table(&mut self) { - if let Some(fse_description) = self.table.cached_encoded_weight_description() { + if let Some(cached) = self.table.cached_encoded_weight_description.get() { + if let Some(fse_description) = cached.as_deref() { + self.writer.write_bits(fse_description.len() as u8, 8); + self.writer.append_bytes(fse_description); + return; + } + let weights = self.weights(); + let weights = &weights[..weights.len() - 1]; // don't encode last weight + Self::write_raw_weight_description(self.writer, weights); + return; + } + + let weights = self.weights(); + let weights = &weights[..weights.len() - 1]; // don't encode last weight + if let Some(fse_description) = self + .table + .cached_encoded_weight_description_with_weights(weights) + { self.writer.write_bits(fse_description.len() as u8, 8); self.writer.append_bytes(fse_description); } else { - let weights = self.weights(); - let weights = &weights[..weights.len() - 1]; // don't encode last weight Self::write_raw_weight_description(self.writer, weights); } } @@ -341,12 +356,17 @@ impl HuffmanTable { } fn cached_encoded_weight_description(&self) -> Option<&[u8]> { + if let Some(cached) = self.cached_encoded_weight_description.get() { + return cached.as_deref(); + } + let weights = self.weights(); + let weights = &weights[..weights.len() - 1]; + self.cached_encoded_weight_description_with_weights(weights) + } + + fn cached_encoded_weight_description_with_weights(&self, weights: &[u8]) -> Option<&[u8]> { self.cached_encoded_weight_description - .get_or_init(|| { - let weights = self.weights(); - let weights = &weights[..weights.len() - 1]; - HuffmanEncoder::>::encode_weight_description(weights) - }) + .get_or_init(|| HuffmanEncoder::>::encode_weight_description(weights)) .as_deref() } @@ -1276,6 +1296,41 @@ fn cached_encoded_weight_description_is_reused_for_write_table() { assert_eq!(&encoded[1..], cached.as_slice()); } +#[test] +fn write_table_raw_path_initializes_none_cache() { + let table = HuffmanTable::build_from_weights(&[1, 1]); + assert!(table.cached_encoded_weight_description.get().is_none()); + + let mut expected = Vec::new(); + let weights = { + let mut out = Vec::new(); + let mut writer = BitWriter::from(&mut out); + let encoder = HuffmanEncoder::new(&table, &mut writer); + encoder.weights() + }; + { + let mut writer = BitWriter::from(&mut expected); + HuffmanEncoder::>::write_raw_weight_description( + &mut writer, + &weights[..weights.len() - 1], + ); + writer.flush(); + } + + let mut encoded = Vec::new(); + { + let mut writer = BitWriter::from(&mut encoded); + let mut encoder = HuffmanEncoder::new(&table, &mut writer); + encoder.write_table(); + writer.flush(); + } + assert_eq!(encoded, expected); + assert_eq!( + table.cached_encoded_weight_description.get().map(Option::is_none), + Some(true) + ); +} + #[test] fn encoded_weight_description_is_accepted_by_donor_huf_reader() { use zstd::zstd_safe::zstd_sys; From 2c7df5b02e2c3618f8515089a6ea53d188c62c41 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 18 May 2026 12:16:32 +0000 Subject: [PATCH 4/6] refactor(huff0): dedupe raw table write path in write_table Agent-Logs-Url: https://github.com/structured-world/structured-zstd/sessions/29cef8e6-3ed8-4ed3-a365-84f0ebf18546 Co-authored-by: polaz <4152123+polaz@users.noreply.github.com> --- zstd/src/huff0/huff0_encoder.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/zstd/src/huff0/huff0_encoder.rs b/zstd/src/huff0/huff0_encoder.rs index cb01a574..51d6a4e3 100644 --- a/zstd/src/huff0/huff0_encoder.rs +++ b/zstd/src/huff0/huff0_encoder.rs @@ -116,9 +116,7 @@ impl>> HuffmanEncoder<'_, '_, V> { self.writer.append_bytes(fse_description); return; } - let weights = self.weights(); - let weights = &weights[..weights.len() - 1]; // don't encode last weight - Self::write_raw_weight_description(self.writer, weights); + self.write_raw_table_description(); return; } @@ -131,10 +129,16 @@ impl>> HuffmanEncoder<'_, '_, V> { self.writer.write_bits(fse_description.len() as u8, 8); self.writer.append_bytes(fse_description); } else { - Self::write_raw_weight_description(self.writer, weights); + self.write_raw_table_description(); } } + fn write_raw_table_description(&mut self) { + let weights = self.weights(); + let weights = &weights[..weights.len() - 1]; // don't encode last weight + Self::write_raw_weight_description(self.writer, weights); + } + /// Encodes Huffman weights using FSE when that representation is valid and beneficial. /// /// Returns `None` when FSE metadata is not suitable, so callers fall back to raw weight encoding. @@ -1325,10 +1329,10 @@ fn write_table_raw_path_initializes_none_cache() { writer.flush(); } assert_eq!(encoded, expected); - assert_eq!( - table.cached_encoded_weight_description.get().map(Option::is_none), - Some(true) - ); + assert!(matches!( + table.cached_encoded_weight_description.get(), + Some(None) + )); } #[test] From bdb20b048b64eea375959107f18ebf647717b3c1 Mon Sep 17 00:00:00 2001 From: Dmitry Prudnikov Date: Mon, 18 May 2026 15:25:19 +0300 Subject: [PATCH 5/6] fix(huff0): preserve Sync auto-trait on HuffmanTable cached description field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `core::cell::OnceCell` is `!Sync`, which made `pub HuffmanTable` silently lose its `Sync` auto-trait when the cache field was added. Downstream consumers sharing encoder tables across threads would see this as a breaking change. Introduce a `CachedDescription` type alias that resolves to: - `std::sync::OnceLock>>` when `feature = "std"` is active — `Sync` via atomic-init, lock-free read-fast-path. - `core::cell::OnceCell>>` otherwise — keeps no_std builds working, narrower thread-safety expected for no_std embedded targets that don't share heap state across threads. Same `get` / `get_or_init` interface in both branches, no call-site changes needed beyond the constructor (`CachedDescription::new()`). Benchmark on `compress/level_2_dfast/small-4k-log-lines/matrix/pure_rust`: 36.0 µs after the switch, within criterion noise of the pre-fix 37.3 µs — the std-build atomic-init read-path is effectively free. --- zstd/src/huff0/huff0_encoder.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/zstd/src/huff0/huff0_encoder.rs b/zstd/src/huff0/huff0_encoder.rs index 51d6a4e3..936c0cd9 100644 --- a/zstd/src/huff0/huff0_encoder.rs +++ b/zstd/src/huff0/huff0_encoder.rs @@ -1,7 +1,18 @@ use alloc::vec::Vec; -use core::cell::OnceCell; use core::cmp::Ordering; +/// Cache primitive for `HuffmanTable::cached_encoded_weight_description`. +/// `std::sync::OnceLock` is `Sync` (atomic-init), so wrapping it inside +/// `pub struct HuffmanTable` keeps the type's auto-traits intact for +/// downstream consumers that share encoder tables across threads. The +/// no_std fallback uses `core::cell::OnceCell` (`!Sync`) — same +/// performance, narrower thread-safety, expected for callers building +/// without `feature = "std"`. +#[cfg(feature = "std")] +type CachedDescription = std::sync::OnceLock>>; +#[cfg(not(feature = "std"))] +type CachedDescription = core::cell::OnceCell>>; + use crate::{ bit_io::BitWriter, fse::fse_encoder::{self, FSEEncoder}, @@ -230,7 +241,7 @@ impl>> HuffmanEncoder<'_, '_, V> { pub struct HuffmanTable { /// Index is the symbol, values are the bitstring in the lower bits of the u32 and the amount of bits in the u8 codes: Vec<(u32, u8)>, - cached_encoded_weight_description: OnceCell>>, + cached_encoded_weight_description: CachedDescription, } impl HuffmanTable { @@ -398,7 +409,7 @@ impl HuffmanTable { let table_log = highest_bit_set(weight_sum) - 1; let mut table = HuffmanTable { codes: alloc::vec![(0, 0); weights.len()], - cached_encoded_weight_description: OnceCell::new(), + cached_encoded_weight_description: CachedDescription::new(), }; let mut nb_per_rank = [0u16; 13]; for &weight in weights { From 747f9d96e641a6810ab33536e5f02e3bcdd134fa Mon Sep 17 00:00:00 2001 From: Dmitry Prudnikov Date: Mon, 18 May 2026 15:48:08 +0300 Subject: [PATCH 6/6] fix(huff0): drop weights recompute in cold-path raw fallback; gate cache to std builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cold-path raw fallback recomputed `weights()` twice — once via `cached_encoded_weight_description_with_weights(weights)` to initialize the cache, then again inside the prior `write_raw_table_description()` helper that fetched its own weights slice. For small / low-cardinality tables that's a measurable hotspot. Inline the raw-write path in `write_table` so it reuses the already-computed `weights` slice in the cold branch, while keeping the cached-`None` sentinel branch using a single fresh recompute (unavoidable — the cache stores only the FSE encoding, not the raw nibbles). The `write_raw_table_description` helper goes away — its one remaining caller was the cached-`None` path, inlined there too. Cache field `cached_encoded_weight_description` is now `#[cfg(feature = "std")]`. `core::cell::OnceCell` is `!Sync`, so in no_std builds the cache would have broken the `Sync` auto-trait for `pub HuffmanTable` — potentially breaking downstream consumers running no_std+alloc with `Arc`. std builds keep `OnceLock>>` (Sync, atomic-init). no_std builds drop the cache field entirely and revert to recompute-every-time — `try_table_description_size` and `write_table` get cfg-branched non-cached paths that match pre-cache semantics exactly. Cache-touching tests are gated on `feature = "std"` so the test suite still compiles in no_std-only configurations. --- zstd/src/huff0/huff0_encoder.rs | 132 +++++++++++++++++++++++--------- 1 file changed, 95 insertions(+), 37 deletions(-) diff --git a/zstd/src/huff0/huff0_encoder.rs b/zstd/src/huff0/huff0_encoder.rs index 936c0cd9..69610de2 100644 --- a/zstd/src/huff0/huff0_encoder.rs +++ b/zstd/src/huff0/huff0_encoder.rs @@ -1,17 +1,19 @@ use alloc::vec::Vec; use core::cmp::Ordering; -/// Cache primitive for `HuffmanTable::cached_encoded_weight_description`. -/// `std::sync::OnceLock` is `Sync` (atomic-init), so wrapping it inside -/// `pub struct HuffmanTable` keeps the type's auto-traits intact for -/// downstream consumers that share encoder tables across threads. The -/// no_std fallback uses `core::cell::OnceCell` (`!Sync`) — same -/// performance, narrower thread-safety, expected for callers building -/// without `feature = "std"`. +/// Cache primitive for `HuffmanTable::cached_encoded_weight_description`, +/// std-only. `std::sync::OnceLock` is `Sync` (atomic-init), so wrapping +/// it inside `pub struct HuffmanTable` keeps the type's auto-traits +/// intact for downstream consumers that share encoder tables across +/// threads. **The cache is entirely absent in no_std builds**: the +/// `cached_encoded_weight_description` field is `#[cfg(feature = "std")]`, +/// so `HuffmanTable` retains `Sync` unconditionally regardless of which +/// feature set the consumer builds with. no_std embedded targets that +/// might run `HuffmanTable` across threads (e.g. via `Arc`) lose the +/// per-table FSE-encode cache as a trade-off — they get the +/// recompute-every-time path that existed before the cache landed. #[cfg(feature = "std")] type CachedDescription = std::sync::OnceLock>>; -#[cfg(not(feature = "std"))] -type CachedDescription = core::cell::OnceCell>>; use crate::{ bit_io::BitWriter, @@ -121,35 +123,56 @@ impl>> HuffmanEncoder<'_, '_, V> { } fn write_table(&mut self) { - if let Some(cached) = self.table.cached_encoded_weight_description.get() { - if let Some(fse_description) = cached.as_deref() { + #[cfg(feature = "std")] + { + // Cached path: cache hit → emit FSE bytes directly OR the + // cached `None` sentinel → emit raw (one `weights()` recompute, + // unavoidable since the cache stores only the FSE encoding, + // not the raw nibbles). + if let Some(cached) = self.table.cached_encoded_weight_description.get() { + if let Some(fse_description) = cached.as_deref() { + self.writer.write_bits(fse_description.len() as u8, 8); + self.writer.append_bytes(fse_description); + return; + } + let weights = self.weights(); + let weights = &weights[..weights.len() - 1]; + Self::write_raw_weight_description(self.writer, weights); + return; + } + // Cold path: compute `weights` once and share it between the + // cache initializer (which uses it to FSE-encode) and the raw + // fallback (which uses it directly to write nibbles). Without + // this, the raw fallback would call back into `weights()` and + // recompute the slice — a measurable hotspot for small / + // low-cardinality tables (#170 review thread). + let weights = self.weights(); + let weights = &weights[..weights.len() - 1]; + if let Some(fse_description) = self + .table + .cached_encoded_weight_description_with_weights(weights) + { self.writer.write_bits(fse_description.len() as u8, 8); self.writer.append_bytes(fse_description); - return; + } else { + Self::write_raw_weight_description(self.writer, weights); } - self.write_raw_table_description(); - return; } - - let weights = self.weights(); - let weights = &weights[..weights.len() - 1]; // don't encode last weight - if let Some(fse_description) = self - .table - .cached_encoded_weight_description_with_weights(weights) + #[cfg(not(feature = "std"))] { - self.writer.write_bits(fse_description.len() as u8, 8); - self.writer.append_bytes(fse_description); - } else { - self.write_raw_table_description(); + // no_std: no cache field, no shared state — single `weights()` + // compute, branch on FSE-vs-raw based on direct encoder call. + let weights = self.weights(); + let weights = &weights[..weights.len() - 1]; + if let Some(fse_description) = Self::encode_weight_description(weights) { + self.writer.write_bits(fse_description.len() as u8, 8); + self.writer.append_bytes(&fse_description); + } else { + Self::write_raw_weight_description(self.writer, weights); + } } } - fn write_raw_table_description(&mut self) { - let weights = self.weights(); - let weights = &weights[..weights.len() - 1]; // don't encode last weight - Self::write_raw_weight_description(self.writer, weights); - } - /// Encodes Huffman weights using FSE when that representation is valid and beneficial. /// /// Returns `None` when FSE metadata is not suitable, so callers fall back to raw weight encoding. @@ -241,6 +264,14 @@ impl>> HuffmanEncoder<'_, '_, V> { pub struct HuffmanTable { /// Index is the symbol, values are the bitstring in the lower bits of the u32 and the amount of bits in the u8 codes: Vec<(u32, u8)>, + /// Lazy cache of the FSE-encoded weight description. Avoids re-running + /// `encode_weight_description` across `try_table_description_size` and + /// `write_table` for the same table instance. **std-only** — + /// `core::cell::OnceCell` is `!Sync` and would break the `Sync` + /// auto-trait for `pub HuffmanTable` in no_std builds; no_std users + /// keep the original recompute-every-time semantics. See the + /// `CachedDescription` type-alias doc above for full rationale. + #[cfg(feature = "std")] cached_encoded_weight_description: CachedDescription, } @@ -344,15 +375,37 @@ impl HuffmanTable { } /// Returns exact writable table-description size when representable. + /// std build path: consults the lazy cache to avoid re-encoding the + /// weight stream when both planner and emitter call this for the + /// same table. no_std build path: recomputes via the direct encoder + /// every call (cache field absent — preserves `Sync`). pub(crate) fn try_table_description_size(&self) -> Option { - if let Some(fse_description) = self.cached_encoded_weight_description() { - return Some(fse_description.len() + 1); + #[cfg(feature = "std")] + { + if let Some(fse_description) = self.cached_encoded_weight_description() { + return Some(fse_description.len() + 1); + } + let raw_weights_len = self.codes.len().saturating_sub(1); + if raw_weights_len <= 128 { + Some(raw_weights_len.div_ceil(2) + 1) + } else { + None + } } - let raw_weights_len = self.codes.len().saturating_sub(1); - if raw_weights_len <= 128 { - Some(raw_weights_len.div_ceil(2) + 1) - } else { - None + #[cfg(not(feature = "std"))] + { + let weights = self.weights(); + let weights = &weights[..weights.len() - 1]; + if let Some(fse_description) = + HuffmanEncoder::>::encode_weight_description(weights) + { + return Some(fse_description.len() + 1); + } + if weights.len() <= 128 { + Some(weights.len().div_ceil(2) + 1) + } else { + None + } } } @@ -370,6 +423,7 @@ impl HuffmanTable { .collect::>() } + #[cfg(feature = "std")] fn cached_encoded_weight_description(&self) -> Option<&[u8]> { if let Some(cached) = self.cached_encoded_weight_description.get() { return cached.as_deref(); @@ -379,6 +433,7 @@ impl HuffmanTable { self.cached_encoded_weight_description_with_weights(weights) } + #[cfg(feature = "std")] fn cached_encoded_weight_description_with_weights(&self, weights: &[u8]) -> Option<&[u8]> { self.cached_encoded_weight_description .get_or_init(|| HuffmanEncoder::>::encode_weight_description(weights)) @@ -409,6 +464,7 @@ impl HuffmanTable { let table_log = highest_bit_set(weight_sum) - 1; let mut table = HuffmanTable { codes: alloc::vec![(0, 0); weights.len()], + #[cfg(feature = "std")] cached_encoded_weight_description: CachedDescription::new(), }; let mut nb_per_rank = [0u16; 13]; @@ -1282,6 +1338,7 @@ fn large_alphabet_weight_description_uses_fse_when_raw_is_unrepresentable() { )); } +#[cfg(feature = "std")] #[test] fn cached_encoded_weight_description_is_reused_for_write_table() { let mut data = Vec::new(); @@ -1311,6 +1368,7 @@ fn cached_encoded_weight_description_is_reused_for_write_table() { assert_eq!(&encoded[1..], cached.as_slice()); } +#[cfg(feature = "std")] #[test] fn write_table_raw_path_initializes_none_cache() { let table = HuffmanTable::build_from_weights(&[1, 1]);