1*3f982cf4SFabien Sanglard// Copyright 2018 The Chromium Authors. All rights reserved. 2*3f982cf4SFabien Sanglard// Use of this source code is governed by a BSD-style license that can be 3*3f982cf4SFabien Sanglard// found in the LICENSE file. 4*3f982cf4SFabien Sanglard 5*3f982cf4SFabien Sanglardpackage osp 6*3f982cf4SFabien Sanglard 7*3f982cf4SFabien Sanglardimport ( 8*3f982cf4SFabien Sanglard "encoding/binary" 9*3f982cf4SFabien Sanglard "errors" 10*3f982cf4SFabien Sanglard "io" 11*3f982cf4SFabien Sanglard) 12*3f982cf4SFabien Sanglard 13*3f982cf4SFabien Sanglardconst ( 14*3f982cf4SFabien Sanglard maxInt6 = 1<<5 - 1 15*3f982cf4SFabien Sanglard maxInt14 = 1<<13 - 1 16*3f982cf4SFabien Sanglard maxInt30 = 1<<29 - 1 17*3f982cf4SFabien Sanglard maxInt62 = 1<<63 - 1 18*3f982cf4SFabien Sanglard) 19*3f982cf4SFabien Sanglard 20*3f982cf4SFabien Sanglard// https://tools.ietf.org/html/draft-ietf-quic-transport-16#section-16 21*3f982cf4SFabien Sanglardfunc ReadVaruint(r io.Reader) (uint64, error) { 22*3f982cf4SFabien Sanglard b0, err := readByte(r) 23*3f982cf4SFabien Sanglard if err != nil { 24*3f982cf4SFabien Sanglard return 0, err 25*3f982cf4SFabien Sanglard } 26*3f982cf4SFabien Sanglard var a [8]byte 27*3f982cf4SFabien Sanglard b := a[:] 28*3f982cf4SFabien Sanglard e := binary.BigEndian 29*3f982cf4SFabien Sanglard b[0] = last6Bits(b0) 30*3f982cf4SFabien Sanglard switch first2Bits(b0) { 31*3f982cf4SFabien Sanglard case 0: 32*3f982cf4SFabien Sanglard return uint64(b[0]), nil 33*3f982cf4SFabien Sanglard case 1: 34*3f982cf4SFabien Sanglard err = readBytes(r, b[1:2]) 35*3f982cf4SFabien Sanglard return uint64(e.Uint16(b)), err 36*3f982cf4SFabien Sanglard case 2: 37*3f982cf4SFabien Sanglard err = readBytes(r, b[1:4]) 38*3f982cf4SFabien Sanglard return uint64(e.Uint32(b)), err 39*3f982cf4SFabien Sanglard case 3: 40*3f982cf4SFabien Sanglard err = readBytes(r, b[1:8]) 41*3f982cf4SFabien Sanglard return uint64(e.Uint64(b)), err 42*3f982cf4SFabien Sanglard } 43*3f982cf4SFabien Sanglard return 0, nil 44*3f982cf4SFabien Sanglard} 45*3f982cf4SFabien Sanglard 46*3f982cf4SFabien Sanglard// https://tools.ietf.org/html/draft-ietf-quic-transport-16#section-16 47*3f982cf4SFabien Sanglardfunc WriteVaruint(v uint64, w io.Writer) error { 48*3f982cf4SFabien Sanglard var a [8]byte 49*3f982cf4SFabien Sanglard b := a[:] 50*3f982cf4SFabien Sanglard e := binary.BigEndian 51*3f982cf4SFabien Sanglard if v <= maxInt6 { 52*3f982cf4SFabien Sanglard b[0] = byte(v) 53*3f982cf4SFabien Sanglard setFirst2Bits(0, b) 54*3f982cf4SFabien Sanglard return writeBytes(b[:1], w) 55*3f982cf4SFabien Sanglard } else if v <= maxInt14 { 56*3f982cf4SFabien Sanglard e.PutUint16(b, uint16(v)) 57*3f982cf4SFabien Sanglard setFirst2Bits(1, b) 58*3f982cf4SFabien Sanglard return writeBytes(b[:2], w) 59*3f982cf4SFabien Sanglard } else if v <= maxInt30 { 60*3f982cf4SFabien Sanglard e.PutUint32(b, uint32(v)) 61*3f982cf4SFabien Sanglard setFirst2Bits(2, b) 62*3f982cf4SFabien Sanglard return writeBytes(b[:4], w) 63*3f982cf4SFabien Sanglard } else if v <= maxInt62 { 64*3f982cf4SFabien Sanglard e.PutUint64(b, v) 65*3f982cf4SFabien Sanglard setFirst2Bits(3, b) 66*3f982cf4SFabien Sanglard return writeBytes(b[:8], w) 67*3f982cf4SFabien Sanglard } 68*3f982cf4SFabien Sanglard return errors.New("Too big") 69*3f982cf4SFabien Sanglard} 70*3f982cf4SFabien Sanglard 71*3f982cf4SFabien Sanglardfunc first2Bits(b byte) byte { 72*3f982cf4SFabien Sanglard return b >> 6 73*3f982cf4SFabien Sanglard} 74*3f982cf4SFabien Sanglard 75*3f982cf4SFabien Sanglardfunc last6Bits(b byte) byte { 76*3f982cf4SFabien Sanglard return b & 0x3f // 0b00111111 77*3f982cf4SFabien Sanglard} 78*3f982cf4SFabien Sanglard 79*3f982cf4SFabien Sanglardfunc setFirst2Bits(first byte, b []byte) { 80*3f982cf4SFabien Sanglard b[0] = (first << 6) | b[0] 81*3f982cf4SFabien Sanglard} 82*3f982cf4SFabien Sanglard 83*3f982cf4SFabien Sanglardfunc readByte(r io.Reader) (byte, error) { 84*3f982cf4SFabien Sanglard var b [1]byte 85*3f982cf4SFabien Sanglard err := readBytes(r, b[:]) 86*3f982cf4SFabien Sanglard return b[0], err 87*3f982cf4SFabien Sanglard} 88*3f982cf4SFabien Sanglard 89*3f982cf4SFabien Sanglard// Read len(b) bytes from r into b 90*3f982cf4SFabien Sanglard// If you hit an error (of the end), propogate the error from r.Read 91*3f982cf4SFabien Sanglardfunc readBytes(r io.Reader, b []byte) error { 92*3f982cf4SFabien Sanglard start := 0 93*3f982cf4SFabien Sanglard end := len(b) 94*3f982cf4SFabien Sanglard for start < end { 95*3f982cf4SFabien Sanglard n, err := r.Read(b[start:end]) 96*3f982cf4SFabien Sanglard if err != nil { 97*3f982cf4SFabien Sanglard return err 98*3f982cf4SFabien Sanglard } 99*3f982cf4SFabien Sanglard start += n 100*3f982cf4SFabien Sanglard } 101*3f982cf4SFabien Sanglard return nil 102*3f982cf4SFabien Sanglard} 103*3f982cf4SFabien Sanglard 104*3f982cf4SFabien Sanglard// Write len(b) bytes from b to w 105*3f982cf4SFabien Sanglard// If you hit an error, propogate the error from w.Write 106*3f982cf4SFabien Sanglardfunc writeBytes(b []byte, w io.Writer) error { 107*3f982cf4SFabien Sanglard start := 0 108*3f982cf4SFabien Sanglard end := len(b) 109*3f982cf4SFabien Sanglard for start < end { 110*3f982cf4SFabien Sanglard n, err := w.Write(b[start:end]) 111*3f982cf4SFabien Sanglard if err != nil { 112*3f982cf4SFabien Sanglard return err 113*3f982cf4SFabien Sanglard } 114*3f982cf4SFabien Sanglard start += n 115*3f982cf4SFabien Sanglard } 116*3f982cf4SFabien Sanglard return nil 117*3f982cf4SFabien Sanglard} 118