1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
pub use alloc::Allocator;
use super::command::Command;
use super::util::floatX;
use super::v8;
use super::s16;
use super::PDF;
use super::interface::StaticCommand;
use super::histogram::{
  HistogramLiteral,
  HistogramCommand,
  HistogramDistance,
  ContextType,
};
use super::cluster::HistogramPair;

use super::entropy_encode::HuffmanTree;
use super::hash_to_binary_tree::ZopfliNode;
#[cfg(feature="std")]
use alloc_stdlib::StandardAlloc;
/*
struct CombiningAllocator<T1, T2, AllocT1:Allocator<T1>, AllocT2:Allocator<T2>>(AllocT1, AllocT2);

impl <T1, T2, AllocT1:Allocator<T1>, AllocT2:Allocator<T2>> CombiningAllocator<T1, T2, AllocT1, AllocT2> {
  pub fn new(a: AllocT1, b: AllocT2) -> Self {
    CombiningAllocator(a, b)
  }
}

impl <T1, T2, AllocT1:Allocator<T1>, AllocT2:Allocator<T2>> Allocator<T1> for CombiningAllocator<T1, T2, AllocT1, AllocT2> {
  
}

      
impl <T1, T2, AllocT1:Allocator<T1>, AllocT2:Allocator<T2>> Allocator<T2> for CombiningAllocator<T1, T2, AllocT1, AllocT2> {
  
}
*/

pub trait BrotliAlloc:Allocator<u8> + Allocator<u16> + Allocator<i32> + Allocator<u32> + Allocator<u64> + Allocator<Command> + Allocator<super::util::floatX> + Allocator<v8> + Allocator<s16> + Allocator<PDF> + Allocator<StaticCommand> + Allocator<HistogramLiteral> + Allocator<HistogramCommand> + Allocator<HistogramDistance> + Allocator<HistogramPair> + Allocator<ContextType> + Allocator<HuffmanTree> + Allocator<ZopfliNode>{
}

#[cfg(feature="std")]
impl BrotliAlloc for StandardAlloc{}

pub struct CombiningAllocator<AllocU8:Allocator<u8>,
                          AllocU16:Allocator<u16>,
                          AllocI32:Allocator<i32>,
                          AllocU32:Allocator<u32>,
                          AllocU64:Allocator<u64>,
                          AllocCommand:Allocator<Command>,
                          AllocFloatX:Allocator<floatX>,
                          AllocV8:Allocator<v8>,
                          AllocS16:Allocator<s16>,
                          AllocPDF:Allocator<PDF>,
                          AllocStaticCommand:Allocator<StaticCommand>,
                          AllocHistogramLiteral:Allocator<HistogramLiteral>,
                          AllocHistogramCommand:Allocator<HistogramCommand>,
                          AllocHistogramDistance:Allocator<HistogramDistance>,
                          AllocHistogramPair:Allocator<HistogramPair>,
                          AllocContextType:Allocator<ContextType>,
                          AllocHuffmanTree:Allocator<HuffmanTree>,
                          AllocZopfliNode:Allocator<ZopfliNode>,
                          >{
  alloc_u8: AllocU8,
  alloc_u16: AllocU16,
  alloc_i32: AllocI32,
  alloc_u32: AllocU32,
  alloc_u64: AllocU64,
  alloc_c: AllocCommand,
  alloc_f: AllocFloatX,
  alloc_f32x8: AllocV8,
  alloc_i16x16: AllocS16,
  alloc_pdf: AllocPDF,
  alloc_sc: AllocStaticCommand,
  alloc_hl: AllocHistogramLiteral,
  alloc_hc: AllocHistogramCommand,
  alloc_hd: AllocHistogramDistance,
  alloc_hp: AllocHistogramPair,
  alloc_ct: AllocContextType,
  alloc_ht: AllocHuffmanTree,
  alloc_zn: AllocZopfliNode,
}

impl<AllocU8:Allocator<u8>,
     AllocU16:Allocator<u16>,
     AllocI32:Allocator<i32>,
     AllocU32:Allocator<u32>,
     AllocU64:Allocator<u64>,
     AllocCommand:Allocator<Command>,
     AllocFloatX:Allocator<floatX>,
     AllocV8:Allocator<v8>,
     AllocS16:Allocator<s16>,
     AllocPDF:Allocator<PDF>,
     AllocStaticCommand:Allocator<StaticCommand>,
     AllocHistogramLiteral:Allocator<HistogramLiteral>,
     AllocHistogramCommand:Allocator<HistogramCommand>,
     AllocHistogramDistance:Allocator<HistogramDistance>,
     AllocHistogramPair:Allocator<HistogramPair>,
     AllocContextType:Allocator<ContextType>,
     AllocHuffmanTree:Allocator<HuffmanTree>,
     AllocZopfliNode:Allocator<ZopfliNode>,
     > CombiningAllocator<AllocU8,
                          AllocU16,
                          AllocI32,
                          AllocU32,
                          AllocU64,
                          AllocCommand,
                          AllocFloatX,
                          AllocV8,
                          AllocS16,
                          AllocPDF,
                          AllocStaticCommand,
                          AllocHistogramLiteral,
                          AllocHistogramCommand,
                          AllocHistogramDistance,
                          AllocHistogramPair,
                          AllocContextType,
                          AllocHuffmanTree,
                          AllocZopfliNode,
                          > {
  pub fn new(alloc_u8: AllocU8,
         alloc_u16: AllocU16,
         alloc_i32: AllocI32,
         alloc_u32: AllocU32,
         alloc_u64: AllocU64,
         alloc_c: AllocCommand,
         alloc_f: AllocFloatX,
         alloc_f32x8: AllocV8,
         alloc_i16x16: AllocS16,
         alloc_pdf: AllocPDF,
         alloc_sc: AllocStaticCommand,
         alloc_hl: AllocHistogramLiteral,
         alloc_hc: AllocHistogramCommand,
         alloc_hd: AllocHistogramDistance,
         alloc_hp: AllocHistogramPair,
         alloc_ct: AllocContextType,
         alloc_ht: AllocHuffmanTree,
         alloc_zn: AllocZopfliNode) -> Self {
    CombiningAllocator{
      alloc_u8:     alloc_u8,
      alloc_u16:    alloc_u16,  
      alloc_i32:   alloc_i32,
      alloc_u32:   alloc_u32, 
      alloc_u64:   alloc_u64, 
      alloc_c:   alloc_c,
      alloc_f:   alloc_f, 
      alloc_f32x8:   alloc_f32x8,
      alloc_i16x16:  alloc_i16x16,
      alloc_pdf:   alloc_pdf,
      alloc_sc:   alloc_sc,
      alloc_hl:   alloc_hl, 
      alloc_hc:   alloc_hc, 
      alloc_hd:   alloc_hd,
      alloc_hp:   alloc_hp, 
      alloc_ct:   alloc_ct, 
      alloc_ht:   alloc_ht,
      alloc_zn:   alloc_zn,
    }
  }
}

  
impl<AllocU8:Allocator<u8>,
     AllocU16:Allocator<u16>,
     AllocI32:Allocator<i32>,
     AllocU32:Allocator<u32>,
     AllocU64:Allocator<u64>,
     AllocCommand:Allocator<Command>,
     AllocFloatX:Allocator<floatX>,
     AllocV8:Allocator<v8>,
     AllocS16:Allocator<s16>,
     AllocPDF:Allocator<PDF>,
     AllocStaticCommand:Allocator<StaticCommand>,
     AllocHistogramLiteral:Allocator<HistogramLiteral>,
     AllocHistogramCommand:Allocator<HistogramCommand>,
     AllocHistogramDistance:Allocator<HistogramDistance>,
     AllocHistogramPair:Allocator<HistogramPair>,
     AllocContextType:Allocator<ContextType>,
     AllocHuffmanTree:Allocator<HuffmanTree>,
     AllocZopfliNode:Allocator<ZopfliNode>,
     > BrotliAlloc for CombiningAllocator<AllocU8,
                                            AllocU16,
                                            AllocI32,
                                            AllocU32,
                                            AllocU64,
                                            AllocCommand,
                                            AllocFloatX,
                                            AllocV8,
                                            AllocS16,
                                            AllocPDF,
                                            AllocStaticCommand,
                                            AllocHistogramLiteral,
                                            AllocHistogramCommand,
                                            AllocHistogramDistance,
                                            AllocHistogramPair,
                                            AllocContextType,
                                            AllocHuffmanTree,
                                            AllocZopfliNode,
                                            > {
}


impl<AllocU8:Allocator<u8>+Default,
     AllocU16:Allocator<u16>+Default,
     AllocI32:Allocator<i32>+Default,
     AllocU32:Allocator<u32>+Default,
     AllocU64:Allocator<u64>+Default,
     AllocCommand:Allocator<Command>+Default,
     AllocFloatX:Allocator<floatX>+Default,
     AllocV8:Allocator<v8>+Default,
     AllocS16:Allocator<s16>+Default,
     AllocPDF:Allocator<PDF>+Default,
     AllocStaticCommand:Allocator<StaticCommand>+Default,
     AllocHistogramLiteral:Allocator<HistogramLiteral>+Default,
     AllocHistogramCommand:Allocator<HistogramCommand>+Default,
     AllocHistogramDistance:Allocator<HistogramDistance>+Default,
     AllocHistogramPair:Allocator<HistogramPair>+Default,
     AllocContextType:Allocator<ContextType>+Default,
     AllocHuffmanTree:Allocator<HuffmanTree>+Default,
     AllocZopfliNode:Allocator<ZopfliNode>+Default,
     > Default for CombiningAllocator<AllocU8,
                          AllocU16,
                          AllocI32,
                          AllocU32,
                          AllocU64,
                          AllocCommand,
                          AllocFloatX,
                          AllocV8,
                          AllocS16,
                          AllocPDF,
                          AllocStaticCommand,
                          AllocHistogramLiteral,
                          AllocHistogramCommand,
                          AllocHistogramDistance,
                          AllocHistogramPair,
                          AllocContextType,
                          AllocHuffmanTree,
                          AllocZopfliNode,
                          > {
    fn default() -> Self {
    CombiningAllocator{
      alloc_u8:  AllocU8::default(),
      alloc_u16: AllocU16::default(),  
      alloc_i32: AllocI32::default(),
      alloc_u32: AllocU32::default(), 
      alloc_u64: AllocU64::default(), 
      alloc_c:   AllocCommand::default(),
      alloc_f:   AllocFloatX::default(), 
      alloc_f32x8:AllocV8::default(),
      alloc_i16x16:AllocS16::default(),
      alloc_pdf: AllocPDF::default(),
      alloc_sc:  AllocStaticCommand::default(),
      alloc_hl:  AllocHistogramLiteral::default(), 
      alloc_hc:  AllocHistogramCommand::default(), 
      alloc_hd:  AllocHistogramDistance::default(),
      alloc_hp:  AllocHistogramPair::default(), 
      alloc_ct:  AllocContextType::default(), 
      alloc_ht:  AllocHuffmanTree::default(),
      alloc_zn:  AllocZopfliNode::default(),
    }
        
    }
}

impl<AllocU8:Allocator<u8>+Clone,
     AllocU16:Allocator<u16>+Clone,
     AllocI32:Allocator<i32>+Clone,
     AllocU32:Allocator<u32>+Clone,
     AllocU64:Allocator<u64>+Clone,
     AllocCommand:Allocator<Command>+Clone,
     AllocFloatX:Allocator<floatX>+Clone,
     AllocV8:Allocator<v8>+Clone,
     AllocS16:Allocator<s16>+Clone,
     AllocPDF:Allocator<PDF>+Clone,
     AllocStaticCommand:Allocator<StaticCommand>+Clone,
     AllocHistogramLiteral:Allocator<HistogramLiteral>+Clone,
     AllocHistogramCommand:Allocator<HistogramCommand>+Clone,
     AllocHistogramDistance:Allocator<HistogramDistance>+Clone,
     AllocHistogramPair:Allocator<HistogramPair>+Clone,
     AllocContextType:Allocator<ContextType>+Clone,
     AllocHuffmanTree:Allocator<HuffmanTree>+Clone,
     AllocZopfliNode:Allocator<ZopfliNode>+Clone,
     > Clone for CombiningAllocator<AllocU8,
                          AllocU16,
                          AllocI32,
                          AllocU32,
                          AllocU64,
                          AllocCommand,
                          AllocFloatX,
                          AllocV8,
                          AllocS16,
                          AllocPDF,
                          AllocStaticCommand,
                          AllocHistogramLiteral,
                          AllocHistogramCommand,
                          AllocHistogramDistance,
                          AllocHistogramPair,
                          AllocContextType,
                          AllocHuffmanTree,
                          AllocZopfliNode,
                                    > {
    fn clone(&self) -> Self {
    CombiningAllocator{
      alloc_u8:  self.alloc_u8.clone(),
      alloc_u16: self.alloc_u16.clone(),  
      alloc_i32: self.alloc_i32.clone(),
      alloc_u32: self.alloc_u32.clone(), 
      alloc_u64: self.alloc_u64.clone(), 
      alloc_c:   self.alloc_c.clone(),
      alloc_f:   self.alloc_f.clone(), 
      alloc_f32x8:self.alloc_f32x8.clone(),
      alloc_i16x16:self.alloc_i16x16.clone(),
      alloc_pdf: self.alloc_pdf.clone(),
      alloc_sc:  self.alloc_sc.clone(),
      alloc_hl:  self.alloc_hl.clone(), 
      alloc_hc:  self.alloc_hc.clone(), 
      alloc_hd:  self.alloc_hd.clone(),
      alloc_hp:  self.alloc_hp.clone(), 
      alloc_ct:  self.alloc_ct.clone(), 
      alloc_ht:  self.alloc_ht.clone(),
      alloc_zn:  self.alloc_zn.clone(),
    }
        
    }
}

impl<AllocU8:Allocator<u8>+Copy,
     AllocU16:Allocator<u16>+Copy,
     AllocI32:Allocator<i32>+Copy,
     AllocU32:Allocator<u32>+Copy,
     AllocU64:Allocator<u64>+Copy,
     AllocCommand:Allocator<Command>+Copy,
     AllocFloatX:Allocator<floatX>+Copy,
     AllocV8:Allocator<v8>+Copy,
     AllocS16:Allocator<s16>+Copy,
     AllocPDF:Allocator<PDF>+Copy,
     AllocStaticCommand:Allocator<StaticCommand>+Copy,
     AllocHistogramLiteral:Allocator<HistogramLiteral>+Copy,
     AllocHistogramCommand:Allocator<HistogramCommand>+Copy,
     AllocHistogramDistance:Allocator<HistogramDistance>+Copy,
     AllocHistogramPair:Allocator<HistogramPair>+Copy,
     AllocContextType:Allocator<ContextType>+Copy,
     AllocHuffmanTree:Allocator<HuffmanTree>+Copy,
     AllocZopfliNode:Allocator<ZopfliNode>+Copy,
     > Copy for CombiningAllocator<AllocU8,
                          AllocU16,
                          AllocI32,
                          AllocU32,
                          AllocU64,
                          AllocCommand,
                          AllocFloatX,
                          AllocV8,
                          AllocS16,
                          AllocPDF,
                          AllocStaticCommand,
                          AllocHistogramLiteral,
                          AllocHistogramCommand,
                          AllocHistogramDistance,
                          AllocHistogramPair,
                          AllocContextType,
                          AllocHuffmanTree,
                          AllocZopfliNode,
                                    > {
}

macro_rules! implement_allocator {
  ($bound_name: ty,
   $type_name: ty,
   $sub_type_name: ty,
   $local_name: ident) => {
    impl<AllocU8:Allocator<u8>,
         AllocU16:Allocator<u16>,
         AllocI32:Allocator<i32>,
         AllocU32:Allocator<u32>,
         AllocU64:Allocator<u64>,
         AllocCommand:Allocator<Command>,
         AllocFloatX:Allocator<floatX>,
         AllocV8:Allocator<v8>,
         AllocS16:Allocator<s16>,
         AllocPDF:Allocator<PDF>,
         AllocStaticCommand:Allocator<StaticCommand>,
         AllocHistogramLiteral:Allocator<HistogramLiteral>,
         AllocHistogramCommand:Allocator<HistogramCommand>,
         AllocHistogramDistance:Allocator<HistogramDistance>,
         AllocHistogramPair:Allocator<HistogramPair>,
         AllocContextType:Allocator<ContextType>,
         AllocHuffmanTree:Allocator<HuffmanTree>,
         AllocZopfliNode:Allocator<ZopfliNode>,
         > Allocator<$type_name> for CombiningAllocator<AllocU8,
                                                 AllocU16,
                                                 AllocI32,
                                                 AllocU32,
                                                 AllocU64,
                                                 AllocCommand,
                                                 AllocFloatX,
                                                 AllocV8,
                                                 AllocS16,
                                                 AllocPDF,
                                                 AllocStaticCommand,
                                                 AllocHistogramLiteral,
                                                 AllocHistogramCommand,
                                                 AllocHistogramDistance,
                                                 AllocHistogramPair,
                                                 AllocContextType,
                                                 AllocHuffmanTree,
                                                 AllocZopfliNode,
                                                 > {
      type AllocatedMemory = $sub_type_name;
      fn alloc_cell(&mut self, size: usize) -> <Self as Allocator<$type_name>>::AllocatedMemory {
        self.$local_name.alloc_cell(size)
      }
      fn free_cell(&mut self, data: <Self as Allocator<$type_name>>::AllocatedMemory) {
        self.$local_name.free_cell(data)
      }
    }
};
}

implement_allocator!(AllocU8, u8, AllocU8::AllocatedMemory, alloc_u8);
implement_allocator!(AllocU16, u16, AllocU16::AllocatedMemory, alloc_u16);

implement_allocator!(AllocI32, i32, AllocI32::AllocatedMemory, alloc_i32);
implement_allocator!(AllocU32, u32, AllocU32::AllocatedMemory, alloc_u32);
implement_allocator!(AllocU64, u64, AllocU64::AllocatedMemory, alloc_u64);
implement_allocator!(AllocCommand, Command, AllocCommand::AllocatedMemory, alloc_c);
implement_allocator!(AllocFloatX, floatX, AllocFloatX::AllocatedMemory, alloc_f);
implement_allocator!(AllocV8, v8, AllocV8::AllocatedMemory, alloc_f32x8);
implement_allocator!(AllocS16, s16, AllocS16::AllocatedMemory, alloc_i16x16);
implement_allocator!(AllocPDF, PDF, AllocPDF::AllocatedMemory, alloc_pdf);
implement_allocator!(AllocStaticCommand, StaticCommand, AllocStaticCommand::AllocatedMemory, alloc_sc);
implement_allocator!(AllocHistogramLiteral, HistogramLiteral, AllocHistogramLiteral::AllocatedMemory, alloc_hl);
implement_allocator!(AllocHistogramCommand, HistogramCommand, AllocHistogramCommand::AllocatedMemory, alloc_hc);
implement_allocator!(AllocHistogramDistance, HistogramDistance, AllocHistogramDistance::AllocatedMemory, alloc_hd);
implement_allocator!(AllocHistogramPair, HistogramPair, AllocHistogramPair::AllocatedMemory, alloc_hp);
implement_allocator!(AllocContextType, ContextType, AllocContextType::AllocatedMemory, alloc_ct);
implement_allocator!(AllocHuffmanTree, HuffmanTree, AllocHuffmanTree::AllocatedMemory, alloc_ht);
implement_allocator!(AllocZopfliNode, ZopfliNode, AllocZopfliNode::AllocatedMemory, alloc_zn);