package utils // HexToCompact converts a hex path to the compact encoded format func HexToCompact(hex []byte) []byte { return hexToCompact(hex) } func hexToCompact(hex []byte) []byte { terminator := byte(0) if hasTerm(hex) { terminator = 1 hex = hex[:len(hex)-1] } buf := make([]byte, len(hex)/2+1) buf[0] = terminator << 5 // the flag byte if len(hex)&1 == 1 { buf[0] |= 1 << 4 // odd flag buf[0] |= hex[0] // first nibble is contained in the first byte hex = hex[1:] } decodeNibbles(hex, buf[1:]) return buf } // CompactToHex converts a compact encoded path to hex format func CompactToHex(compact []byte) []byte { return compactToHex(compact) } func compactToHex(compact []byte) []byte { if len(compact) == 0 { return compact } base := KeybytesToHex(compact) // delete terminator flag if base[0] < 2 { base = base[:len(base)-1] } // apply odd flag chop := 2 - base[0]&1 return base[chop:] } func KeybytesToHex(str []byte) []byte { l := len(str)*2 + 1 var nibbles = make([]byte, l) for i, b := range str { nibbles[i*2] = b / 16 nibbles[i*2+1] = b % 16 } nibbles[l-1] = 16 return nibbles } func decodeNibbles(nibbles []byte, bytes []byte) { for bi, ni := 0, 0; ni < len(nibbles); bi, ni = bi+1, ni+2 { bytes[bi] = nibbles[ni]<<4 | nibbles[ni+1] } } // hasTerm returns whether a hex key has the terminator flag. func hasTerm(s []byte) bool { return len(s) > 0 && s[len(s)-1] == 16 }