File: binary.go

package info (click to toggle)
android-platform-tools 34.0.5-12
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 150,900 kB
  • sloc: cpp: 805,786; java: 293,500; ansic: 128,288; xml: 127,491; python: 41,481; sh: 14,245; javascript: 9,665; cs: 3,846; asm: 2,049; makefile: 1,917; yacc: 440; awk: 368; ruby: 183; sql: 140; perl: 88; lex: 67
file content (117 lines) | stat: -rw-r--r-- 2,351 bytes parent folder | download | duplicates (11)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package osp

import (
	"encoding/binary"
	"errors"
	"io"
)

const (
	maxInt6  = 1<<5 - 1
	maxInt14 = 1<<13 - 1
	maxInt30 = 1<<29 - 1
	maxInt62 = 1<<63 - 1
)

// https://tools.ietf.org/html/draft-ietf-quic-transport-16#section-16
func ReadVaruint(r io.Reader) (uint64, error) {
	b0, err := readByte(r)
	if err != nil {
		return 0, err
	}
	var a [8]byte
	b := a[:]
	e := binary.BigEndian
	b[0] = last6Bits(b0)
	switch first2Bits(b0) {
	case 0:
		return uint64(b[0]), nil
	case 1:
		err = readBytes(r, b[1:2])
		return uint64(e.Uint16(b)), err
	case 2:
		err = readBytes(r, b[1:4])
		return uint64(e.Uint32(b)), err
	case 3:
		err = readBytes(r, b[1:8])
		return uint64(e.Uint64(b)), err
	}
	return 0, nil
}

// https://tools.ietf.org/html/draft-ietf-quic-transport-16#section-16
func WriteVaruint(v uint64, w io.Writer) error {
	var a [8]byte
	b := a[:]
	e := binary.BigEndian
	if v <= maxInt6 {
		b[0] = byte(v)
		setFirst2Bits(0, b)
		return writeBytes(b[:1], w)
	} else if v <= maxInt14 {
		e.PutUint16(b, uint16(v))
		setFirst2Bits(1, b)
		return writeBytes(b[:2], w)
	} else if v <= maxInt30 {
		e.PutUint32(b, uint32(v))
		setFirst2Bits(2, b)
		return writeBytes(b[:4], w)
	} else if v <= maxInt62 {
		e.PutUint64(b, v)
		setFirst2Bits(3, b)
		return writeBytes(b[:8], w)
	}
	return errors.New("Too big")
}

func first2Bits(b byte) byte {
	return b >> 6
}

func last6Bits(b byte) byte {
	return b & 0x3f // 0b00111111
}

func setFirst2Bits(first byte, b []byte) {
	b[0] = (first << 6) | b[0]
}

func readByte(r io.Reader) (byte, error) {
	var b [1]byte
	err := readBytes(r, b[:])
	return b[0], err
}

// Read len(b) bytes from r into b
// If you hit an error (of the end), propogate the error from r.Read
func readBytes(r io.Reader, b []byte) error {
	start := 0
	end := len(b)
	for start < end {
		n, err := r.Read(b[start:end])
		if err != nil {
			return err
		}
		start += n
	}
	return nil
}

// Write len(b) bytes from b to w
// If you hit an error, propogate the error from w.Write
func writeBytes(b []byte, w io.Writer) error {
	start := 0
	end := len(b)
	for start < end {
		n, err := w.Write(b[start:end])
		if err != nil {
			return err
		}
		start += n
	}
	return nil
}