From 89ec7ed9ee7d7c16cb947ce1f67282c14efa54e1 Mon Sep 17 00:00:00 2001 From: MM Date: Wed, 13 Nov 2024 07:51:53 +0100 Subject: [PATCH] default impl in trait are not accessible? --- src/generic.rs | 164 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 107 insertions(+), 57 deletions(-) diff --git a/src/generic.rs b/src/generic.rs index 5c4e99d..ecaf32a 100644 --- a/src/generic.rs +++ b/src/generic.rs @@ -1,122 +1,172 @@ -/// Generic functions +/// Generic functions `encode` and `decode` that taken an instance the `Encoding` trait. +/// The encode and decode come also in the flavour Encoding::encode and Encoding::decode. +/// +/// The point of the whole commotion is to have single generic encode and decode +/// function that is better suited to generic programming than the wrappers codec::enc, dec, etc. +/// +/// There are four such `Encoding` instances: +/// - `StandardEncoding` for unsorted integer lists (using codec::dec and enc) +/// - `IncreasingEncoding` for increasing integer lists (using codec::ddec and denc) +/// - `StrictlyIncreasingEncoding` for strictly increasing integer lists (using codec::d1dec and d1enc) +/// - `ZigZagEncoding` for unsorted integer lists (using codec::zdec and zenc) +/// +/// Along with those two function we have `dec_buf_len` and `enc_buf_size` that are used to calculate +/// the safe buffer sizes. +/// +/// Each encoding gets an u8 identifier `ENC_TYPE` that can be used for lookup tables, etc. +/// +/// The sample function is used to generate random data for testing the encodings. use crate::codec::*; use crate::sample::*; use std::marker::PhantomData; -use rand::{ +use std::mem; +use rand::{ // for testing prelude::Distribution, - distributions::Standard + distributions::Standard, }; +pub trait EncodingBase { + type W: Width; +} + +pub struct StandardEncodingBase { _wt: PhantomData } +pub struct IncreasingEncodingBase { _wt: PhantomData } +pub struct StrictlyIncreasingEncodingBase { _wt: PhantomData } +pub struct ZigZagEncodingBase { _wt: PhantomData } + +impl EncodingBase for StandardEncodingBase { type W = WT; } +impl EncodingBase for IncreasingEncodingBase { type W = WT; } +impl EncodingBase for StrictlyIncreasingEncodingBase { type W = WT; } +impl EncodingBase for ZigZagEncodingBase { type W = WT; } + +/// Trait for encoding types with width. pub trait Encoding { + type W: Width; type T; - const ENC_TYPE: u8; // useful for identifying the encoding type in lookup tables, etc. - fn encode(input: &[Self::T], output: &mut [u8]) -> usize; - fn decode(input: &[u8], n: usize, output: &mut [Self::T]) -> usize; + /// Numeric ID useful for identifying the encoding type in lookup tables, etc. + const ENC_TYPE: u8; + /// Encode input data into output buffer + fn encode(input: &[Self::T], output: &mut [u8]) -> usize; + /// Decode input buffer into output data + fn decode(input: &[u8], n: usize, output: &mut [Self::T]) -> usize; + /// Minimum safe [T] array length required for decoding n T's + fn dec_buf_len(n: usize) -> usize; + /// Minimum safe u8 size required for encoding n T's + fn enc_buf_size(n: usize) -> usize; + /// Sample random data for Self::T suitable for testing this encoding fn sample(len: usize) -> Vec; } -pub struct StandardEncoding { _marker_w: PhantomData, _marker_t: PhantomData } -pub struct IncreasingEncoding { _marker_w: PhantomData, _marker_t: PhantomData } -pub struct StrictlyIncreasingEncoding { _marker_w: PhantomData, _marker_t: PhantomData } -pub struct ZigZagEncoding { _marker_w: PhantomData, _marker_t: PhantomData } +pub struct StandardEncoding { _marker_w: PhantomData, _marker_t: PhantomData } +pub struct IncreasingEncoding { _marker_w: PhantomData, _marker_t: PhantomData } +pub struct StrictlyIncreasingEncoding { _marker_w: PhantomData, _marker_t: PhantomData } +pub struct ZigZagEncoding { _marker_w: PhantomData, _marker_t: PhantomData } // Implement the Encoding trait for each encoding type, linking to the right Codec methods -impl> Encoding for StandardEncoding +impl> Encoding for StandardEncoding where Standard: Distribution, T: Arithmetic { + type W = WT; type T = T; const ENC_TYPE: u8 = 0; // Example encoding type constant - fn encode(input: &[Self::T], output: &mut [u8]) -> usize { + fn encode(input: &[Self::T], output: &mut [u8]) -> usize { T::enc(input, output) } - fn decode(input: &[u8], n: usize, output: &mut [Self::T]) -> usize { + fn decode(input: &[u8], n: usize, output: &mut [Self::T]) -> usize { T::dec(input, n, output) } + fn dec_buf_len(n: usize) -> usize { Self::W::dec_buf_len::(n) } + fn enc_buf_size(n: usize) -> usize { Self::W::enc_buf_size::(n) } fn sample(len: usize) -> Vec { sample_standard(len) } } -impl> Encoding for IncreasingEncoding +impl> Encoding for IncreasingEncoding where Standard: Distribution, T: Arithmetic { + type W = WT; type T = T; const ENC_TYPE: u8 = 1; - fn encode(input: &[Self::T], output: &mut [u8]) -> usize { + fn encode(input: &[Self::T], output: &mut [u8]) -> usize { T::denc(input, output) } - fn decode(input: &[u8], n: usize, output: &mut [Self::T]) -> usize { + fn decode(input: &[u8], n: usize, output: &mut [Self::T]) -> usize { T::ddec(input, n, output) } + fn dec_buf_len(n: usize) -> usize { Self::W::dec_buf_len::(n) } + fn enc_buf_size(n: usize) -> usize { Self::W::enc_buf_size::(n) } fn sample(len: usize) -> Vec where Standard: Distribution, T: Arithmetic { sample_increasing(len, 0, 10) } } -impl> Encoding for StrictlyIncreasingEncoding +impl> Encoding for StrictlyIncreasingEncoding where Standard: Distribution, T: Arithmetic { + type W = WT; type T = T; const ENC_TYPE: u8 = 2; - fn encode(input: &[Self::T], output: &mut [u8]) -> usize { + fn encode(input: &[Self::T], output: &mut [u8]) -> usize { T::d1enc(input, output) } - fn decode(input: &[u8], n: usize, output: &mut [Self::T]) -> usize { + fn decode(input: &[u8], n: usize, output: &mut [Self::T]) -> usize { T::d1dec(input, n, output) } + fn dec_buf_len(n: usize) -> usize { Self::W::dec_buf_len::(n) } + fn enc_buf_size(n: usize) -> usize { Self::W::enc_buf_size::(n) } fn sample(len: usize) -> Vec where Standard: Distribution, T: Arithmetic { sample_increasing(len, 1, 10) } } -impl> Encoding for ZigZagEncoding +impl> Encoding for ZigZagEncoding where Standard: Distribution, T: Arithmetic { + type W = WT; type T = T; const ENC_TYPE: u8 = 3; - fn encode(input: &[Self::T], output: &mut [u8]) -> usize { + fn encode(input: &[Self::T], output: &mut [u8]) -> usize { T::zenc(input, output) } - fn decode(input: &[u8], n: usize, output: &mut [Self::T]) -> usize { + fn decode(input: &[u8], n: usize, output: &mut [Self::T]) -> usize { T::zdec(input, n, output) } + fn dec_buf_len(n: usize) -> usize { Self::W::dec_buf_len::(n) } + fn enc_buf_size(n: usize) -> usize { Self::W::enc_buf_size::(n) } fn sample(len: usize) -> Vec { sample_standard(len) } } /// Generic encoding function -pub fn encode(input: &[E::T], output: &mut [u8]) -> usize { - E::encode::(input, output) +pub fn encode(input: &[E::T], output: &mut [u8]) -> usize { + E::encode(input, output) } /// Generic decoding function -pub fn decode(input: &[u8], n: usize, output: &mut [E::T]) -> usize { - E::decode::(input, n, output) +pub fn decode(input: &[u8], n: usize, output: &mut [E::T]) -> usize { + E::decode(input, n, output) } #[cfg(test)] use rand::Rng; #[cfg(test)] -fn test_enc_dec_generic() +fn test_enc_dec_generic() where - WidthType: Width, - E: Encoding, - T: Codec, - T: Eq + Clone + core::fmt::Debug + Default, - u8: Codec, u16: Codec, u32: Codec, u64: Codec, - Standard: Distribution, T: Arithmetic + E: Encoding, + E::T : Default + std::fmt::Debug, + E::W : Width, + Standard: Distribution, E::T: Arithmetic { let mut rng = rand::thread_rng(); for _ in 0..256 { // Generate random input data let len = rng.gen_range(1..=16 * 1024); - let input: Vec = E::sample(len); - println!("Input: {:?}", input); + let input: Vec = E::sample(len); // Prepare input buffer and encode - let mut buf = vec![0u8; WidthType::enc_buf_size::(input.len())]; - let size_enc = encode::(&input, &mut buf); + let mut buf = vec![0u8; E::enc_buf_size(input.len())]; + let size_enc = encode::(&input, &mut buf); // Prepare output buffer and decode - let mut output: Vec = vec![T::default(); WidthType::dec_buf_len::(input.len())]; - println!("Output: {:?}", output); - let size_dec = decode::(&buf[..size_enc], input.len(), &mut output); + let mut output: Vec = vec![E::T::default(); E::dec_buf_len(input.len())]; + let size_dec = decode::(&buf[..size_enc], input.len(), &mut output); // Check results assert_eq!(size_enc, size_dec); assert_eq!(input, output[..input.len()]); @@ -125,80 +175,80 @@ where #[test] fn test_enc_dec_u8_standard() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u16_standard() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u32_standard() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u64_standard() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u8_increasing() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u16_increasing() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u32_increasing() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u64_increasing() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u8_strictly_increasing() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u16_strictly_increasing() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u32_strictly_increasing() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u64_strictly_increasing() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u8_zigzag() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u16_zigzag() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u32_zigzag() { - test_enc_dec_generic::, W>() + test_enc_dec_generic::>() } #[test] fn test_enc_dec_u64_zigzag() { - test_enc_dec_generic::, W>() -} + test_enc_dec_generic::>() +} \ No newline at end of file