1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-05-06 19:29:15 +08:00
Dušan Borovčanin 55e09c1921
MF-1506 - Group-based Access Control (#1716)
* Move Things and Users to Clients

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Update Add and Delete Policies (#1792)

* Remove Policy Action Ranks

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Rebase Issues

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix CI Test Errors

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Adding Check on Subject For Clients

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Remove Check Client Exists

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Check When Sharing Clients

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Only Add User to Group When Sharing Things

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Remove clientType

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Minor Fix on ShareClient and Fix Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Policies Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Clean Up Things Authorization

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests on RetrieveAll

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Test ShareThing

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Merge Conflicts

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Remove Adding Policies. Only Use Ownership

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Check If Subject is same as Object

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Move Back To Union As Sometimes Policy is Empty and Fails to Evaluate on Ownership

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Entity Type For Failing Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix BUG in policy evaluation

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Comments Regarding checkAdmin

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests On Rebase

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Combine Authorize For Things and Users

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests On Rebase

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Error on Things SVC `unsupported protocol scheme`

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* Fix Bug on Things Authorization Cache (#1810)

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* Use Password instead of username in MQTT handler

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* Simplify MQTT authorization

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* Fix MQTT tests

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Add More Functions to SDK (#1811)

* Add More Functions to SDK

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Examples to GoDoc

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Update Unassign Interface

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Pass Subject as ID and Not Token on List Channels By Thing

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Bootstrap Errors For Element Check

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add empty line Before Return

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Reorder URLS in things mux

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Listing Things Policies

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Share Thing

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Examples to CLI Docs

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Update Identity To Update Another User

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Identify an Update Policies on Things

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Update Things Policies

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix GoDocs on Disconnect

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Change Authorize To Use AccessRequest

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* For Evaluate Policy Use AccessRequest (#1814)

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Add SDK Tests (#1812)

* Add Things Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Channel Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Certs Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Consumer Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Enrich Group Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Tests For Health

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Tests For Tokens

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Rename SDK for Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Policies Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Linter

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Fix Tests

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Make Variable Defination Inline

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Make Cache Key Duration Configurable (#1815)

* Make Cache Key Duration Configurable

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Rename ENV Var

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Update GoDocs (#1816)

* Add GoDocs

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add Missing GoDoc Files

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Enable godot

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

* Add License Information

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>

---------

Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

* NOISSUE - Add Call Home Client to Mainflux services (#1751)

* Move Things and Users to Clients

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: SammyOina <sammyoina@gmail.com>

* collect and send data package

Signed-off-by: SammyOina <sammyoina@gmail.com>

* create telemetry migrations

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add telemetry endpoints

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add transport

Signed-off-by: SammyOina <sammyoina@gmail.com>

* create service

Signed-off-by: SammyOina <sammyoina@gmail.com>

* remove homing server

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add call home to adapters

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add last seen

Signed-off-by: SammyOina <sammyoina@gmail.com>

* rename logger

Signed-off-by: SammyOina <sammyoina@gmail.com>

* remove homing client

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use unmerged repo

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use renamed module

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update call home version

Signed-off-by: SammyOina <sammyoina@gmail.com>

* edit documentation

Signed-off-by: SammyOina <sammyoina@gmail.com>

* align table

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use alias for call home client

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update callhome

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update call home pkg

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update call home

Signed-off-by: SammyOina <sammyoina@gmail.com>

* fix modules

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use mf build version

Signed-off-by: SammyOina <sammyoina@gmail.com>

* use mf build version

Signed-off-by: SammyOina <sammyoina@gmail.com>

* restore default

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add call home for users and things

Signed-off-by: SammyOina <sammyoina@gmail.com>

* enable opting on call home

Signed-off-by: SammyOina <sammyoina@gmail.com>

* remove full stops

Signed-off-by: SammyOina <sammyoina@gmail.com>

* update callhome client

Signed-off-by: SammyOina <sammyoina@gmail.com>

* add call home to all services

Signed-off-by: SammyOina <sammyoina@gmail.com>

* fix build

Signed-off-by: SammyOina <sammyoina@gmail.com>

* restore sdk tests

Signed-off-by: SammyOina <sammyoina@gmail.com>

* remove unnecessary changes

Signed-off-by: SammyOina <sammyoina@gmail.com>

* restore health_test.go

Signed-off-by: SammyOina <sammyoina@gmail.com>

---------

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: SammyOina <sammyoina@gmail.com>
Co-authored-by: b1ackd0t <blackd0t@protonmail.com>
Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>

---------

Signed-off-by: dusanb94 <dusan.borovcanin@mainflux.com>
Signed-off-by: rodneyosodo <blackd0t@protonmail.com>
Signed-off-by: SammyOina <sammyoina@gmail.com>
Co-authored-by: b1ackd0t <blackd0t@protonmail.com>
Co-authored-by: Sammy Kerata Oina <44265300+SammyOina@users.noreply.github.com>
2023-06-14 12:40:37 +02:00

548 lines
13 KiB
Go

// Copyright 2018 The Go 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 protowire parses and formats the raw wire encoding.
// See https://protobuf.dev/programming-guides/encoding.
//
// For marshaling and unmarshaling entire protobuf messages,
// use the "google.golang.org/protobuf/proto" package instead.
package protowire
import (
"io"
"math"
"math/bits"
"google.golang.org/protobuf/internal/errors"
)
// Number represents the field number.
type Number int32
const (
MinValidNumber Number = 1
FirstReservedNumber Number = 19000
LastReservedNumber Number = 19999
MaxValidNumber Number = 1<<29 - 1
DefaultRecursionLimit = 10000
)
// IsValid reports whether the field number is semantically valid.
func (n Number) IsValid() bool {
return MinValidNumber <= n && n <= MaxValidNumber
}
// Type represents the wire type.
type Type int8
const (
VarintType Type = 0
Fixed32Type Type = 5
Fixed64Type Type = 1
BytesType Type = 2
StartGroupType Type = 3
EndGroupType Type = 4
)
const (
_ = -iota
errCodeTruncated
errCodeFieldNumber
errCodeOverflow
errCodeReserved
errCodeEndGroup
errCodeRecursionDepth
)
var (
errFieldNumber = errors.New("invalid field number")
errOverflow = errors.New("variable length integer overflow")
errReserved = errors.New("cannot parse reserved wire type")
errEndGroup = errors.New("mismatching end group marker")
errParse = errors.New("parse error")
)
// ParseError converts an error code into an error value.
// This returns nil if n is a non-negative number.
func ParseError(n int) error {
if n >= 0 {
return nil
}
switch n {
case errCodeTruncated:
return io.ErrUnexpectedEOF
case errCodeFieldNumber:
return errFieldNumber
case errCodeOverflow:
return errOverflow
case errCodeReserved:
return errReserved
case errCodeEndGroup:
return errEndGroup
default:
return errParse
}
}
// ConsumeField parses an entire field record (both tag and value) and returns
// the field number, the wire type, and the total length.
// This returns a negative length upon an error (see ParseError).
//
// The total length includes the tag header and the end group marker (if the
// field is a group).
func ConsumeField(b []byte) (Number, Type, int) {
num, typ, n := ConsumeTag(b)
if n < 0 {
return 0, 0, n // forward error code
}
m := ConsumeFieldValue(num, typ, b[n:])
if m < 0 {
return 0, 0, m // forward error code
}
return num, typ, n + m
}
// ConsumeFieldValue parses a field value and returns its length.
// This assumes that the field Number and wire Type have already been parsed.
// This returns a negative length upon an error (see ParseError).
//
// When parsing a group, the length includes the end group marker and
// the end group is verified to match the starting field number.
func ConsumeFieldValue(num Number, typ Type, b []byte) (n int) {
return consumeFieldValueD(num, typ, b, DefaultRecursionLimit)
}
func consumeFieldValueD(num Number, typ Type, b []byte, depth int) (n int) {
switch typ {
case VarintType:
_, n = ConsumeVarint(b)
return n
case Fixed32Type:
_, n = ConsumeFixed32(b)
return n
case Fixed64Type:
_, n = ConsumeFixed64(b)
return n
case BytesType:
_, n = ConsumeBytes(b)
return n
case StartGroupType:
if depth < 0 {
return errCodeRecursionDepth
}
n0 := len(b)
for {
num2, typ2, n := ConsumeTag(b)
if n < 0 {
return n // forward error code
}
b = b[n:]
if typ2 == EndGroupType {
if num != num2 {
return errCodeEndGroup
}
return n0 - len(b)
}
n = consumeFieldValueD(num2, typ2, b, depth-1)
if n < 0 {
return n // forward error code
}
b = b[n:]
}
case EndGroupType:
return errCodeEndGroup
default:
return errCodeReserved
}
}
// AppendTag encodes num and typ as a varint-encoded tag and appends it to b.
func AppendTag(b []byte, num Number, typ Type) []byte {
return AppendVarint(b, EncodeTag(num, typ))
}
// ConsumeTag parses b as a varint-encoded tag, reporting its length.
// This returns a negative length upon an error (see ParseError).
func ConsumeTag(b []byte) (Number, Type, int) {
v, n := ConsumeVarint(b)
if n < 0 {
return 0, 0, n // forward error code
}
num, typ := DecodeTag(v)
if num < MinValidNumber {
return 0, 0, errCodeFieldNumber
}
return num, typ, n
}
func SizeTag(num Number) int {
return SizeVarint(EncodeTag(num, 0)) // wire type has no effect on size
}
// AppendVarint appends v to b as a varint-encoded uint64.
func AppendVarint(b []byte, v uint64) []byte {
switch {
case v < 1<<7:
b = append(b, byte(v))
case v < 1<<14:
b = append(b,
byte((v>>0)&0x7f|0x80),
byte(v>>7))
case v < 1<<21:
b = append(b,
byte((v>>0)&0x7f|0x80),
byte((v>>7)&0x7f|0x80),
byte(v>>14))
case v < 1<<28:
b = append(b,
byte((v>>0)&0x7f|0x80),
byte((v>>7)&0x7f|0x80),
byte((v>>14)&0x7f|0x80),
byte(v>>21))
case v < 1<<35:
b = append(b,
byte((v>>0)&0x7f|0x80),
byte((v>>7)&0x7f|0x80),
byte((v>>14)&0x7f|0x80),
byte((v>>21)&0x7f|0x80),
byte(v>>28))
case v < 1<<42:
b = append(b,
byte((v>>0)&0x7f|0x80),
byte((v>>7)&0x7f|0x80),
byte((v>>14)&0x7f|0x80),
byte((v>>21)&0x7f|0x80),
byte((v>>28)&0x7f|0x80),
byte(v>>35))
case v < 1<<49:
b = append(b,
byte((v>>0)&0x7f|0x80),
byte((v>>7)&0x7f|0x80),
byte((v>>14)&0x7f|0x80),
byte((v>>21)&0x7f|0x80),
byte((v>>28)&0x7f|0x80),
byte((v>>35)&0x7f|0x80),
byte(v>>42))
case v < 1<<56:
b = append(b,
byte((v>>0)&0x7f|0x80),
byte((v>>7)&0x7f|0x80),
byte((v>>14)&0x7f|0x80),
byte((v>>21)&0x7f|0x80),
byte((v>>28)&0x7f|0x80),
byte((v>>35)&0x7f|0x80),
byte((v>>42)&0x7f|0x80),
byte(v>>49))
case v < 1<<63:
b = append(b,
byte((v>>0)&0x7f|0x80),
byte((v>>7)&0x7f|0x80),
byte((v>>14)&0x7f|0x80),
byte((v>>21)&0x7f|0x80),
byte((v>>28)&0x7f|0x80),
byte((v>>35)&0x7f|0x80),
byte((v>>42)&0x7f|0x80),
byte((v>>49)&0x7f|0x80),
byte(v>>56))
default:
b = append(b,
byte((v>>0)&0x7f|0x80),
byte((v>>7)&0x7f|0x80),
byte((v>>14)&0x7f|0x80),
byte((v>>21)&0x7f|0x80),
byte((v>>28)&0x7f|0x80),
byte((v>>35)&0x7f|0x80),
byte((v>>42)&0x7f|0x80),
byte((v>>49)&0x7f|0x80),
byte((v>>56)&0x7f|0x80),
1)
}
return b
}
// ConsumeVarint parses b as a varint-encoded uint64, reporting its length.
// This returns a negative length upon an error (see ParseError).
func ConsumeVarint(b []byte) (v uint64, n int) {
var y uint64
if len(b) <= 0 {
return 0, errCodeTruncated
}
v = uint64(b[0])
if v < 0x80 {
return v, 1
}
v -= 0x80
if len(b) <= 1 {
return 0, errCodeTruncated
}
y = uint64(b[1])
v += y << 7
if y < 0x80 {
return v, 2
}
v -= 0x80 << 7
if len(b) <= 2 {
return 0, errCodeTruncated
}
y = uint64(b[2])
v += y << 14
if y < 0x80 {
return v, 3
}
v -= 0x80 << 14
if len(b) <= 3 {
return 0, errCodeTruncated
}
y = uint64(b[3])
v += y << 21
if y < 0x80 {
return v, 4
}
v -= 0x80 << 21
if len(b) <= 4 {
return 0, errCodeTruncated
}
y = uint64(b[4])
v += y << 28
if y < 0x80 {
return v, 5
}
v -= 0x80 << 28
if len(b) <= 5 {
return 0, errCodeTruncated
}
y = uint64(b[5])
v += y << 35
if y < 0x80 {
return v, 6
}
v -= 0x80 << 35
if len(b) <= 6 {
return 0, errCodeTruncated
}
y = uint64(b[6])
v += y << 42
if y < 0x80 {
return v, 7
}
v -= 0x80 << 42
if len(b) <= 7 {
return 0, errCodeTruncated
}
y = uint64(b[7])
v += y << 49
if y < 0x80 {
return v, 8
}
v -= 0x80 << 49
if len(b) <= 8 {
return 0, errCodeTruncated
}
y = uint64(b[8])
v += y << 56
if y < 0x80 {
return v, 9
}
v -= 0x80 << 56
if len(b) <= 9 {
return 0, errCodeTruncated
}
y = uint64(b[9])
v += y << 63
if y < 2 {
return v, 10
}
return 0, errCodeOverflow
}
// SizeVarint returns the encoded size of a varint.
// The size is guaranteed to be within 1 and 10, inclusive.
func SizeVarint(v uint64) int {
// This computes 1 + (bits.Len64(v)-1)/7.
// 9/64 is a good enough approximation of 1/7
return int(9*uint32(bits.Len64(v))+64) / 64
}
// AppendFixed32 appends v to b as a little-endian uint32.
func AppendFixed32(b []byte, v uint32) []byte {
return append(b,
byte(v>>0),
byte(v>>8),
byte(v>>16),
byte(v>>24))
}
// ConsumeFixed32 parses b as a little-endian uint32, reporting its length.
// This returns a negative length upon an error (see ParseError).
func ConsumeFixed32(b []byte) (v uint32, n int) {
if len(b) < 4 {
return 0, errCodeTruncated
}
v = uint32(b[0])<<0 | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
return v, 4
}
// SizeFixed32 returns the encoded size of a fixed32; which is always 4.
func SizeFixed32() int {
return 4
}
// AppendFixed64 appends v to b as a little-endian uint64.
func AppendFixed64(b []byte, v uint64) []byte {
return append(b,
byte(v>>0),
byte(v>>8),
byte(v>>16),
byte(v>>24),
byte(v>>32),
byte(v>>40),
byte(v>>48),
byte(v>>56))
}
// ConsumeFixed64 parses b as a little-endian uint64, reporting its length.
// This returns a negative length upon an error (see ParseError).
func ConsumeFixed64(b []byte) (v uint64, n int) {
if len(b) < 8 {
return 0, errCodeTruncated
}
v = uint64(b[0])<<0 | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
return v, 8
}
// SizeFixed64 returns the encoded size of a fixed64; which is always 8.
func SizeFixed64() int {
return 8
}
// AppendBytes appends v to b as a length-prefixed bytes value.
func AppendBytes(b []byte, v []byte) []byte {
return append(AppendVarint(b, uint64(len(v))), v...)
}
// ConsumeBytes parses b as a length-prefixed bytes value, reporting its length.
// This returns a negative length upon an error (see ParseError).
func ConsumeBytes(b []byte) (v []byte, n int) {
m, n := ConsumeVarint(b)
if n < 0 {
return nil, n // forward error code
}
if m > uint64(len(b[n:])) {
return nil, errCodeTruncated
}
return b[n:][:m], n + int(m)
}
// SizeBytes returns the encoded size of a length-prefixed bytes value,
// given only the length.
func SizeBytes(n int) int {
return SizeVarint(uint64(n)) + n
}
// AppendString appends v to b as a length-prefixed bytes value.
func AppendString(b []byte, v string) []byte {
return append(AppendVarint(b, uint64(len(v))), v...)
}
// ConsumeString parses b as a length-prefixed bytes value, reporting its length.
// This returns a negative length upon an error (see ParseError).
func ConsumeString(b []byte) (v string, n int) {
bb, n := ConsumeBytes(b)
return string(bb), n
}
// AppendGroup appends v to b as group value, with a trailing end group marker.
// The value v must not contain the end marker.
func AppendGroup(b []byte, num Number, v []byte) []byte {
return AppendVarint(append(b, v...), EncodeTag(num, EndGroupType))
}
// ConsumeGroup parses b as a group value until the trailing end group marker,
// and verifies that the end marker matches the provided num. The value v
// does not contain the end marker, while the length does contain the end marker.
// This returns a negative length upon an error (see ParseError).
func ConsumeGroup(num Number, b []byte) (v []byte, n int) {
n = ConsumeFieldValue(num, StartGroupType, b)
if n < 0 {
return nil, n // forward error code
}
b = b[:n]
// Truncate off end group marker, but need to handle denormalized varints.
// Assuming end marker is never 0 (which is always the case since
// EndGroupType is non-zero), we can truncate all trailing bytes where the
// lower 7 bits are all zero (implying that the varint is denormalized).
for len(b) > 0 && b[len(b)-1]&0x7f == 0 {
b = b[:len(b)-1]
}
b = b[:len(b)-SizeTag(num)]
return b, n
}
// SizeGroup returns the encoded size of a group, given only the length.
func SizeGroup(num Number, n int) int {
return n + SizeTag(num)
}
// DecodeTag decodes the field Number and wire Type from its unified form.
// The Number is -1 if the decoded field number overflows int32.
// Other than overflow, this does not check for field number validity.
func DecodeTag(x uint64) (Number, Type) {
// NOTE: MessageSet allows for larger field numbers than normal.
if x>>3 > uint64(math.MaxInt32) {
return -1, 0
}
return Number(x >> 3), Type(x & 7)
}
// EncodeTag encodes the field Number and wire Type into its unified form.
func EncodeTag(num Number, typ Type) uint64 {
return uint64(num)<<3 | uint64(typ&7)
}
// DecodeZigZag decodes a zig-zag-encoded uint64 as an int64.
//
// Input: {…, 5, 3, 1, 0, 2, 4, 6, …}
// Output: {…, -3, -2, -1, 0, +1, +2, +3, …}
func DecodeZigZag(x uint64) int64 {
return int64(x>>1) ^ int64(x)<<63>>63
}
// EncodeZigZag encodes an int64 as a zig-zag-encoded uint64.
//
// Input: {…, -3, -2, -1, 0, +1, +2, +3, …}
// Output: {…, 5, 3, 1, 0, 2, 4, 6, …}
func EncodeZigZag(x int64) uint64 {
return uint64(x<<1) ^ uint64(x>>63)
}
// DecodeBool decodes a uint64 as a bool.
//
// Input: { 0, 1, 2, …}
// Output: {false, true, true, …}
func DecodeBool(x uint64) bool {
return x != 0
}
// EncodeBool encodes a bool as a uint64.
//
// Input: {false, true}
// Output: { 0, 1}
func EncodeBool(x bool) uint64 {
if x {
return 1
}
return 0
}