main
Raw Download raw file
 1// Copyright 2017 The Go Authors. All rights reserved.
 2// Use of this source code is governed by a BSD-style
 3// license that can be found in the LICENSE file.
 4
 5package encoding
 6
 7import (
 8	"io"
 9
10	"github.com/ProtonMail/go-crypto/openpgp/errors"
11)
12
13// OID is used to store a variable-length field with a one-octet size
14// prefix. See https://tools.ietf.org/html/rfc6637#section-9.
15type OID struct {
16	bytes []byte
17}
18
19const (
20	// maxOID is the maximum number of bytes in a OID.
21	maxOID = 254
22	// reservedOIDLength1 and reservedOIDLength2 are OID lengths that the RFC
23	// specifies are reserved.
24	reservedOIDLength1 = 0
25	reservedOIDLength2 = 0xff
26)
27
28// NewOID returns a OID initialized with bytes.
29func NewOID(bytes []byte) *OID {
30	switch len(bytes) {
31	case reservedOIDLength1, reservedOIDLength2:
32		panic("encoding: NewOID argument length is reserved")
33	default:
34		if len(bytes) > maxOID {
35			panic("encoding: NewOID argument too large")
36		}
37	}
38
39	return &OID{
40		bytes: bytes,
41	}
42}
43
44// Bytes returns the decoded data.
45func (o *OID) Bytes() []byte {
46	return o.bytes
47}
48
49// BitLength is the size in bits of the decoded data.
50func (o *OID) BitLength() uint16 {
51	return uint16(len(o.bytes) * 8)
52}
53
54// EncodedBytes returns the encoded data.
55func (o *OID) EncodedBytes() []byte {
56	return append([]byte{byte(len(o.bytes))}, o.bytes...)
57}
58
59// EncodedLength is the size in bytes of the encoded data.
60func (o *OID) EncodedLength() uint16 {
61	return uint16(1 + len(o.bytes))
62}
63
64// ReadFrom reads into b the next OID from r.
65func (o *OID) ReadFrom(r io.Reader) (int64, error) {
66	var buf [1]byte
67	n, err := io.ReadFull(r, buf[:])
68	if err != nil {
69		if err == io.EOF {
70			err = io.ErrUnexpectedEOF
71		}
72		return int64(n), err
73	}
74
75	switch buf[0] {
76	case reservedOIDLength1, reservedOIDLength2:
77		return int64(n), errors.UnsupportedError("reserved for future extensions")
78	}
79
80	o.bytes = make([]byte, buf[0])
81
82	nn, err := io.ReadFull(r, o.bytes)
83	if err == io.EOF {
84		err = io.ErrUnexpectedEOF
85	}
86
87	return int64(n) + int64(nn), err
88}