xref: /aosp_15_r20/external/openscreen/osp/go/binary.go (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
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