Encodes a 32 bytes word, trying to optimize it as much as possible
(word []byte, saveWord bool)
| 10 | |
| 11 | // Encodes a 32 bytes word, trying to optimize it as much as possible |
| 12 | func (buf *Buffer) EncodeWordOptimized(word []byte, saveWord bool) ([]byte, EncodeType, error) { |
| 13 | if len(word) > 32 { |
| 14 | return nil, Stateless, fmt.Errorf("word exceeds 32 bytes") |
| 15 | } |
| 16 | |
| 17 | trimmed := bytes.TrimLeft(word, "\x00") |
| 18 | |
| 19 | // Trimmed right must be computed with the word (left padded) to 32 bytes |
| 20 | padded32 := make([]byte, 32) |
| 21 | copy(padded32[32-len(word):], word) |
| 22 | trimmedRight := bytes.TrimRight(padded32, "\x00") |
| 23 | |
| 24 | // If empty then it can be encoded as literal zero |
| 25 | if buf.Allows(LITERAL_ZERO) && len(trimmed) == 0 { |
| 26 | return []byte{byte(LITERAL_ZERO)}, Stateless, nil |
| 27 | } |
| 28 | |
| 29 | // Literals are the cheapest encoding |
| 30 | if buf.Allows(LITERAL_ZERO) && len(trimmed) <= 1 && trimmed[0] <= byte(MAX_LITERAL) { |
| 31 | return []byte{trimmed[0] + byte(LITERAL_ZERO)}, Stateless, nil |
| 32 | } |
| 33 | |
| 34 | // If it only has 1 byte, then we encode it as a word |
| 35 | // all other methods use 2 bytes anyway |
| 36 | if buf.Allows(FLAG_READ_WORD_1) && len(trimmed) == 1 { |
| 37 | return buf.EncodeWordBytes32(trimmed) |
| 38 | } |
| 39 | |
| 40 | // If the word is a power of 2 or 10, we can encode it using 1 byte |
| 41 | pow2 := isPow2(trimmed) |
| 42 | if buf.Allows(FLAG_POW_2) && pow2 != -1 { |
| 43 | return []byte{byte(FLAG_POW_2), byte(pow2)}, Stateless, nil |
| 44 | } |
| 45 | |
| 46 | // Pow 10 can be encoded as 10 ** N, this uses 1 byte |
| 47 | pow10 := isPow10(trimmed) |
| 48 | if buf.Allows(FLAG_POW_10) && pow10 != -1 && pow10 != 0 && pow10 <= 77 { |
| 49 | return []byte{byte(FLAG_POW_10), byte(pow10)}, Stateless, nil |
| 50 | } |
| 51 | |
| 52 | // 2 ** n - 1 can be represented by 1 byte |
| 53 | // we need to subtract 1 from the value, or else we can't represent 2 ** 256 - 1 |
| 54 | pow2minus1 := isPow2minus1(trimmed) |
| 55 | if buf.Allows(FLAG_POW_2_MINUS_1) && pow2minus1 != -1 { |
| 56 | // The opcode adds an extra 1 to the value, so we need to subtract 1 |
| 57 | return []byte{byte(FLAG_POW_2_MINUS_1), byte(pow2minus1 - 1)}, Stateless, nil |
| 58 | } |
| 59 | |
| 60 | // Now we can store words of 2 bytes, we have exhausted all the 1 byte options |
| 61 | if buf.Allows(FLAG_READ_WORD_1) && len(trimmed) <= 2 { |
| 62 | return buf.EncodeWordBytes32(trimmed) |
| 63 | } |
| 64 | |
| 65 | // Trimmed right inv uses 1 extra byte (so 2 bytes overhead) |
| 66 | if buf.Allows(FLAG_READ_WORD_INV) && len(trimmedRight) == 1 { |
| 67 | return buf.EncodeWordBytes32Inv(trimmedRight) |
| 68 | } |
| 69 |
no test coverage detected