package goavro import ( "encoding/binary" "fmt" "io" ) // rabinEmpty is a constant used to initialize the crc64Table, and to compute // the CRC-64-AVRO fingerprint of every object schema. const rabinEmpty = uint64(0xc15d213aa4d7a795) // rabinTable is never modified after initialization but its values are read to // compute the CRC-64-AVRO fingerprint of every schema its given. var rabinTable = [256]uint64{ 0, 3238593523956797946, 6477187047913595892, 8435907220062204430, 12954374095827191784, 11472609148414072338, 16871814440124408860, 14327483619285186022, 16515860097293205755, 14539261057490653441, 13607494391182877455, 10387063993012335349, 6265406319754774291, 8791864835633305321, 1085550678754862311, 2585467722461443357, 5247393906202824413, 7215812591205457703, 1239030555549527337, 4449591751341063379, 18092457712352332085, 15556728100436498639, 11742789833002527425, 10234164645493242683, 12530812639509548582, 9302088354573213660, 17583729671266610642, 15633189885995973672, 2171101357509724622, 3661574416647526452, 5170935444922886714, 7724537325157989312, 10494787812405648826, 13642865964979244096, 14431625182410915406, 16480541316673728436, 2478061111099054674, 1049933365183482792, 8899183502682126758, 6300970840149272668, 8399466921467862337, 6368420890995002555, 3275086581351513781, 108854135608684367, 14364169659802000041, 16980263386864569171, 11435870349096892765, 12845837170396948647, 15669858317114364775, 17692196227407282845, 9265331945857609875, 12422293323479818601, 7688114635962061967, 5062151678603773301, 3698085083440658299, 2279937883717887617, 4342202715019449244, 1203395666939462246, 7323148833295052904, 5282940851558637970, 10341870889845773428, 11778178981837571470, 15449074650315978624, 18057156506771531386, 11669866394404287583, 10160817855121008037, 17874829710049597355, 15339802717267265105, 1311848476550706103, 4523114428088083021, 5464845951130112067, 7432843562972398009, 4956122222198109348, 7509300761534850398, 2099866730366965584, 3591042414950500010, 17798367005364253516, 15848531969535615670, 12601941680298545336, 9372796311334617410, 16798933842935724674, 14253900473960229752, 12736841781990005110, 11255500115345754252, 6550173162703027562, 8509314479008689296, 217708271217368734, 3455596968422674276, 870833084869474937, 2370047569572014979, 6194214610827729293, 8721096401170761847, 13822387873690697105, 10602378625989962859, 16587157392570359397, 14609853536892473247, 3483332339477899749, 2064482512161650719, 7616958077116566033, 4991418462803860459, 9480190278288059917, 12637572737790640119, 15741190762473065977, 17762823925471730691, 15376229271924123934, 17983608511393921252, 10124303357207546602, 11561034798826117904, 7396170166881316598, 5356383260452470540, 4559875767435775234, 1420363961462201592, 8684405430038898488, 6085769495188764354, 2406791333878924492, 979366144819647798, 14646297666590105808, 16695918618875998506, 10565881703117275940, 13713538703073841886, 11362911691697612739, 12772455230081578553, 14146576876296094775, 16763373153642681805, 3347869283551649835, 182341662412566993, 8616954185191982047, 6585487012709290533, 13933329357911598997, 17126321439046432367, 11006435164953838689, 12992741788688209307, 8257930048646602877, 6803747195591438727, 3132703159877387145, 542775339377431155, 2623696953101412206, 619515277774763668, 9046228856176166042, 5871394916501263712, 10929691902260224134, 13501751302614184316, 14865687125944796018, 16338017159720129160, 9912244444396218696, 11925134239902742706, 15018601523069700796, 18202706530865158982, 4199733460733931168, 1637543290675756890, 7182084829901000020, 5717935174548446382, 7834929158557182387, 4632665972928804937, 3844057317981030983, 1849042541720329149, 16103865201353027163, 17549867708331900833, 9700748483321744815, 12280807109898935381, 5834933197202143791, 8937414855024798677, 655924238275353051, 2732422975565056033, 16374796089197559239, 14974255385173568573, 13465025131935292979, 10821211621719183305, 13100346325406055124, 11041713811386575662, 17018628958017378592, 13897997918303815898, 435416542434737468, 3097107305413864646, 6911193936845348552, 8293578696285179698, 1741666169738949874, 3808479038558283016, 4740095139144029958, 7870595381236532988, 12388429221655458586, 9736009554713699040, 17442192802341523694, 16068516186704462100, 18239503069743100937, 15127152172900050419, 11888425678624364541, 9803746554456753671, 5681455845848806369, 7073288438148047387, 1673934641775824917, 4308477092595991023, 6966664678955799498, 5503217582476919344, 4128965024323301438, 1566351579938693572, 15233916154233132066, 18417600011429070296, 9982836925607720918, 11996431537128302124, 9627165335515697969, 12207926510359495371, 15886756170769674437, 17332335396841578815, 3917464579278591193, 1922028658990515491, 8051932600676513581, 4850374241660872407, 2917466598601071895, 327962119137676525, 8187398044598779619, 6732512565967646489, 11221777246008269567, 13207379120439233285, 14004037317153847563, 17197450482186430705, 14792340333762633196, 16265093719173729302, 10712766520904941080, 13284123302255603682, 9119751534871550468, 5944212839312182270, 2840727922924403184, 836967320887912458, 17368810860077796976, 15995557527495450506, 12171538990377528708, 9518416773021940862, 4813582667757848984, 7943378085384837218, 1958732289639295596, 4025966300338256790, 1458733299300535947, 4093699022299389809, 5610888623004134783, 7002018658576923781, 12103802978479819107, 10018419036150929561, 18310175810188503703, 15198246066092718957, 13391477134206599341, 10748366240846565719, 16157651908532642649, 14756687855020634787, 729366649650267973, 2805444311502067391, 6051901489239909553, 9155087905094251851, 6695738567103299670, 8078825954266321324, 364683324825133986, 3025950744619954776, 17233908370383964094, 14112856248920397380, 13170974025418581066, 11113046258555286960, } // rabin returns an unsigned 64-bit integer Rabin fingerprint for buf. NOTE: // This is only used during Codec instantiation to calculate the Rabin // fingerprint of the canonical schema. func rabin(buf []byte) uint64 { fp := rabinEmpty for i := 0; i < len(buf); i++ { fp = (fp >> 8) ^ rabinTable[(byte(fp)^buf[i])&0xff] // unsigned right shift >>> } return fp } const soeMagicPrefix = 2 // 2-byte prefix for SOE encoded data const soeHeaderLen = soeMagicPrefix + 8 // 2-byte prefix plus 8-byte fingerprint // FingerprintFromSOE returns the unsigned 64-bit Rabin fingerprint from the // header of a buffer that encodes a Single-Object Encoded datum. This function // is designed to be used to lookup a Codec that can decode the contents of the // buffer. Once a Codec is found that has the matching Rabin fingerprint, its // NativeFromBinary method may be used to decode the remaining bytes returned as // the second return value. On failure this function returns an // ErrNotSingleObjectEncoded error. // // func decode(codex map[uint64]*goavro.Codec, buf []byte) error { // // Perform a sanity check on the buffer, then return the Rabin fingerprint // // of the schema used to encode the data. // fingerprint, newBuf, err := goavro.FingerprintFromSOE(buf) // if err != nil { // return err // } // // // Get a previously stored Codec from the codex map. // codec, ok := codex[fingerprint] // if !ok { // return fmt.Errorf("unknown codec: %#x", fingerprint) // } // // // Use the fetched Codec to decode the buffer as a SOE. // // // // Faster because SOE magic prefix and schema fingerprint already // // checked and used to fetch the Codec. Just need to decode the binary // // bytes remaining after the prefix were removed. // datum, _, err := codec.NativeFromBinary(newBuf) // if err != nil { // return err // } // // _, err = fmt.Println(datum) // return err // } func FingerprintFromSOE(buf []byte) (uint64, []byte, error) { if len(buf) < soeHeaderLen { // Not enough bytes to encode schema fingerprint. return 0, nil, ErrNotSingleObjectEncoded(io.ErrShortBuffer.Error()) } if buf[0] != 0xC3 || buf[1] != 0x01 { // Currently only one SOE prefix is recognized. return 0, nil, ErrNotSingleObjectEncoded(fmt.Sprintf("unknown SOE prefix: %#x", buf[:soeMagicPrefix])) } // Only recognizes single-object encodings format version 1. return binary.LittleEndian.Uint64(buf[soeMagicPrefix:]), buf[soeHeaderLen:], nil }