|  | // Copyright 2019 The Wuffs Authors. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //    https://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | // ---------------- | 
|  |  | 
|  | // Package compression provides common types for other compression packages. | 
|  | package compression | 
|  |  | 
|  | import ( | 
|  | "io" | 
|  | ) | 
|  |  | 
|  | // Reader is an io.ReadCloser with a Reset method. | 
|  | type Reader interface { | 
|  | io.ReadCloser | 
|  |  | 
|  | // Reset resets this Reader to switch to a new underlying io.Reader. This | 
|  | // permits re-using a Reader instead of allocating a new one. | 
|  | // | 
|  | // It is the same as the standard library's zlib.Resetter's method. | 
|  | Reset(r io.Reader, dictionary []byte) error | 
|  | } | 
|  |  | 
|  | // Writer is an io.WriteCloser with a Reset method. | 
|  | type Writer interface { | 
|  | io.WriteCloser | 
|  |  | 
|  | // Reset resets this Writer to switch to a new underlying io.Writer. This | 
|  | // permits re-using a Writer instead of allocating a new one. | 
|  | Reset(w io.Writer, dictionary []byte, level Level) error | 
|  | } | 
|  |  | 
|  | // Level configures the compression trade-off between speed and size. | 
|  | // | 
|  | // A lower (more negative) value means better speed (faster). A higher (more | 
|  | // positive) value means better size (smaller). | 
|  | type Level int32 | 
|  |  | 
|  | const ( | 
|  | // LevelFastest means to maximize compression speed. | 
|  | LevelFastest Level = -2 << 10 | 
|  |  | 
|  | // LevelFast means to prioritize compression speed. | 
|  | // | 
|  | // It might not be as fast as LevelFastest, if doing so would require | 
|  | // substantial additional compute resources (e.g. CPU or RAM) or give up | 
|  | // substantial compression size. | 
|  | LevelFast Level = -1 << 10 | 
|  |  | 
|  | // LevelDefault means to use a reasonable default. | 
|  | LevelDefault Level = 0 | 
|  |  | 
|  | // LevelSmall means to prioritize compression size. | 
|  | // | 
|  | // It might not be as small as LevelSmallest, if doing so would require | 
|  | // substantial additional compute resources (e.g. CPU or RAM) or give up | 
|  | // substantial compression speed. | 
|  | LevelSmall Level = +1 << 10 | 
|  |  | 
|  | // LevelSmallest means to minimize compression size. | 
|  | LevelSmallest Level = +2 << 10 | 
|  |  | 
|  | // gap is the difference between each named Level. | 
|  | gap = 1 << 10 | 
|  | ) | 
|  |  | 
|  | // Interpolate translates from Level (a codec-independent concept) to a | 
|  | // codec-specific compression level numbering scheme. For exampe, a zlib | 
|  | // package might translate LevelFastest to 1 and LevelSmallest to 9 by calling | 
|  | // Interpolate(1, 2, 6, 9, 9). | 
|  | // | 
|  | // The mapping is via piecewise linear interpolation, given by five points in | 
|  | // (Level, int32) space: (LevelFastest, fastest), (LevelFast, fast), etc. | 
|  | func (l Level) Interpolate(fastest int32, fast int32, default_ int32, small int32, smallest int32) int32 { | 
|  | if l == 0 { | 
|  | return default_ | 
|  | } else if l <= LevelFastest { | 
|  | return fastest | 
|  | } else if l <= LevelFast { | 
|  | return interpolate(-l+LevelFast, fast, fastest) | 
|  | } else if l < 0 { | 
|  | return interpolate(-l, default_, fast) | 
|  | } else if l >= LevelSmallest { | 
|  | return smallest | 
|  | } else if l >= LevelSmall { | 
|  | return interpolate(+l-LevelSmall, small, smallest) | 
|  | } else if l > 0 { | 
|  | return interpolate(+l, default_, small) | 
|  | } | 
|  | panic("unreachable") | 
|  | } | 
|  |  | 
|  | func interpolate(relative Level, ia int32, ib int32) int32 { | 
|  | x := int64(ib-ia) * int64(relative) / gap | 
|  | return ia + int32(x) | 
|  | } |