Simplify unmarshalling.

This commit is contained in:
Henrik, Sölver
2021-06-09 19:51:48 +02:00
committed by Henrik Sölver
parent 61abe8dbd4
commit 71fcac40f0
17 changed files with 452 additions and 179 deletions

View File

@@ -36,9 +36,32 @@ func (b *Boolean) valueTag() tag {
return booleanValueTag
}
func unmarshalSingleAttribute(byteStream io.Reader) (string, []byte) {
var length uint16
binary.Read(byteStream, binary.BigEndian, &length)
attributeName := make([]byte, length)
if length > 0 {
binary.Read(byteStream, binary.BigEndian, attributeName)
}
binary.Read(byteStream, binary.BigEndian, &length)
attributeValue := make([]byte, length)
binary.Read(byteStream, binary.BigEndian, attributeValue)
return string(attributeName), attributeValue
}
func (b *Boolean) unmarshal(byteStream io.Reader) {
name, data := unmarshalSingleAttribute(byteStream)
b.name = name
var length uint16
binary.Read(byteStream, binary.BigEndian, &length)
attributeName := make([]byte, length)
if length > 0 {
binary.Read(byteStream, binary.BigEndian, attributeName)
}
b.name = string(attributeName)
binary.Read(byteStream, binary.BigEndian, &length)
data := make([]byte, length)
binary.Read(byteStream, binary.BigEndian, data)
//name, data := unmarshalSingleAttribute(byteStream)
if data[0] == 0 {
b.value = false
return
@@ -60,9 +83,4 @@ func (b *Boolean) marshal() []byte {
buf.WriteByte(byte(0))
}
return buf.Bytes()
}
func (b *Boolean) size() int {
l := 5 + len(b.name)
return l
}
}

View File

@@ -45,10 +45,3 @@ func (c *CharSetValue) marshal() []byte {
func (c *CharSetValue) marshalInto([]byte) int {
return 0
}
func (c *CharSetValue) size() int {
l := 1 + 4 // The attribute tag + 2 lengths
l += len(c.name)
l += len(c.value)
return l
}

View File

@@ -0,0 +1,94 @@
34
00 00
00 11 // Name length
6d 65 64 69 61 2d 63 6f 6c 2d 64 65 66 61 75 6c 74 // "media-col-default"
00 00 // Always zero
4a // Collection member
00 00 // Always zero
00 0a // Value length
6d 65 64 69 61 2d 74 79 70 65 // "media-type"
44 // Keyword
00 00 00 0a
73 74 61 74 69 6f 6e 65 72 79 // "stationery"
4a // Collection member
00 00 // Always zero
00 0a // Value length
6d 65 64 69 61 2d 73 69 7a 65 // Member name "media-size"
34 // Begin Collection
00 00 // Name Length (In this case there is no name)
00 00 // Always zero
4a
00 00
00 0b
78 2d 64 69 6d 65 6e 73 69 6f 6e // "x-dimension"
21 // Integer value
00 00
00 04
00 00 52 08
4a
00 00
00 0b
79 2d 64 69 6d 65 6e 73 69 6f 6e // "y-dimension"
21 // Integer value
00 00
00 04
00 00 74 04
37 00 00 00 00 // End
4a
00 00
00 13
6d 65 64 69 61 2d 62 6f 74 74 6f 6d 2d 6d 61 72 67 69 6e // "media-bottom-margin"
21
00 00
00 04
00 00 01 b0
4a
00 00
00 11
6d 65 64 69 61 2d 6c 65 66 74 2d 6d 61 72 67 69 6e
21
00 00
00 04
00 00 01 b0
4a
00 00
00 12
6d 65 64 69 61 2d 72 69 67 68 74 2d 6d 61 72 67 69 6e // "media-right-margin"
21 00 00 00 04 00 00 01 b0
4a
00 00
00 10
6d 65 64 69 61 2d 74 6f 70 2d 6d 61 72 67 69 6e
21 00 00 00 04 00 00 01 b0
4a
00 00
00 0c
6d 65 64 69 61 2d 73 6f 75 72 63 65 // "media-source"
44 // Keyword
00 00
00 04
61 75 74 6f // "auto"
37 00 00 00 00 // End
23 00 1d 6f 72 69 65 6e 74 61 74 69 6f 6e 2d 72 65
From ipptool
media-col-default (collection) =
{media-type=stationery media-size={x-dimension=21000 y-dimension=29700}
media-bottom-margin=432
media-left-margin=432
media-right-margin=432
media-top-margin=432 media-source=auto}

View File

@@ -3,6 +3,7 @@
package ipp
import (
"bufio"
"fmt"
)
@@ -30,10 +31,6 @@ func (e *Enum) valueTag() tag {
return enumValueTag
}
func (e *Enum) size() int {
return 9 + len(e.name)
}
func (e *Enum) addValue(v interface{}) {
e.values = append(e.values, v.(int32))
}
@@ -41,3 +38,11 @@ func (e *Enum) addValue(v interface{}) {
func (e *Enum) marshal() []byte {
return marshalInteger(enumValueTag, e.name, e.values)
}
func (e *Enum) unmarshal(byteStream *bufio.Reader) {
soi, err := unmarshalIntegers(byteStream, integerValueTag)
if err != nil {
return
}
e.values = soi.values
}

View File

@@ -3,10 +3,10 @@
package ipp
import (
"bufio"
"bytes"
"encoding/binary"
"fmt"
"io"
)
type Integer struct {
@@ -33,10 +33,6 @@ func (i *Integer) valueTag() tag {
return integerValueTag
}
func (i *Integer) size() int {
return 9 + len(i.name) // The attribute tag + 2 lengths
}
func (i *Integer) addValue(v interface{}) {
i.values = append(i.values, v.(int32))
}
@@ -45,6 +41,15 @@ func (i *Integer) marshal() []byte {
return marshalInteger(integerValueTag, i.name, i.values)
}
func (i *Integer) unmarshal(byteStream *bufio.Reader) {
soi, err := unmarshalIntegers(byteStream, integerValueTag)
if err != nil {
return
}
i.name = soi.name
i.values = soi.values
}
func marshalInteger(t tag, name string, values []int32) []byte {
l := 9 + len(name) + 9*(len(values)-1)
b := make([]byte, 0, l)
@@ -62,8 +67,3 @@ func marshalInteger(t tag, name string, values []int32) []byte {
}
return buf.Bytes()
}
func unmarshalSingleInteger(byteStream io.Reader) (string, int32) {
name, data := unmarshalSingleAttribute(byteStream)
return name, int32(binary.BigEndian.Uint32(data))
}

View File

@@ -3,6 +3,7 @@
package ipp
import (
"bufio"
"bytes"
"testing"
@@ -18,10 +19,12 @@ func TestUnMarshalSinglePositiveInteger(T *testing.T) {
}
buf := bytes.NewBuffer(testdata)
bufbuf := bufio.NewReader(buf)
n, v := unmarshalSingleInteger(buf)
assert.Equal(T, "flop", n, "Should be equal")
assert.Equal(T, int32(4), v, "Should be equal")
var i Integer
i.unmarshal(bufbuf)
assert.Equal(T, "flop", i.name, "Should be equal")
assert.Equal(T, int32(4), i.values[0], "Should be equal")
}
func TestUnMarshalSingleNegativeInteger(T *testing.T) {
@@ -31,10 +34,11 @@ func TestUnMarshalSingleNegativeInteger(T *testing.T) {
0x00, 0x04,
0xff, 0xff, 0xff, 0xfc,
}
buf := bytes.NewBuffer(testdata)
bufbuf := bufio.NewReader(buf)
n, v := unmarshalSingleInteger(buf)
assert.Equal(T, "flop", n, "Should be equal")
assert.Equal(T, int32(-4), v, "Should be equal")
var i Integer
i.unmarshal(bufbuf)
assert.Equal(T, "flop", i.name, "Should be equal")
assert.Equal(T, int32(-4), i.values[0], "Should be equal")
}

View File

@@ -2,6 +2,10 @@
// SPDX-License-Identifier: BSD-3-Clause
package ipp
import (
"bufio"
)
type KeyWord struct {
sos *SetOfStrings
}
@@ -21,10 +25,6 @@ func (k KeyWord) String() string {
return k.sos.String()
}
func (k *KeyWord) size() int {
return k.sos.size()
}
func (k *KeyWord) valueTag() tag {
return k.sos.valueTag()
}
@@ -33,7 +33,10 @@ func (k *KeyWord) marshal() []byte {
return k.sos.marshal()
}
func (k *KeyWord) unmarshal(byteStream *bufio.Reader) {
k.sos.unmarshal(byteStream, keyWordValueTag)
}
func (k *KeyWord) addValue(v interface{}) {
k.sos.AddValue(v.(string))
}

View File

@@ -3,6 +3,8 @@
package ipp
import (
"bufio"
"bytes"
"testing"
"github.com/stretchr/testify/assert"
@@ -22,6 +24,28 @@ import (
// assert.Equal(T, k.values[0], "printer-make-and-model")
// }
func TestUnmarshalKeywordWithMultipleStrings(t *testing.T) {
// test data from rfc8010 example A8 Get-Jobs request
testdata := []byte{0x00, 0x14,
'r', 'e', 'q', 'u', 'e', 's', 't', 'e', 'd', '-', 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's',
0x00, 0x06,
'j', 'o', 'b', '-', 'i', 'd',
0x44, 0x00, 0x00, 0x00, 0x08,
'j', 'o', 'b', '-', 'n', 'a', 'm', 'e',
0x44, 0x00, 0x00, 0x00, 0x0f,
'd', 'o', 'c', 'u', 'm', 'e', 'n', 't', '-', 'f', 'o', 'r', 'm', 'a', 't',
}
buf := bytes.NewBuffer(testdata)
r := bufio.NewReader(buf)
k := NewKeyWord("")
k.unmarshal(r)
assert.Equal(t, k.Name(), "requested-attributes")
assert.Len(t, k.sos.values, 3)
assert.Equal(t, k.sos.values[0], "job-id")
assert.Equal(t, k.sos.values[1], "job-name")
assert.Equal(t, k.sos.values[2], "document-format")
}
func TestMarshalSimpleKeyword(T *testing.T) {
testdata := []byte{
0x44, 0x00, 0x14,
@@ -36,3 +60,28 @@ func TestMarshalSimpleKeyword(T *testing.T) {
assert.Equal(T, testdata, m, "Should be equal")
}
func TestUnMarshalKeywordWithAdditionalValues(T *testing.T) {
testdata := []byte{
0x00, 0x04,
0x72, 0x65, 0x71, 0x75,
0x00, 0x06,
0x70, 0x72, 0x69, 0x6e, 0x74, 0x65,
0x44, 0x00, 0x00,
0x00, 0x04,
0x6e, 0x69, 0x72, 0x70,
0x44, 0x00, 0x00,
0x00, 0x05,
0x70, 0x72, 0x69, 0x6e, 0x74, 0x00,
}
b := bytes.NewBuffer(testdata)
buf := bufio.NewReader(b)
k := NewKeyWord("")
k.unmarshal(buf)
assert.Equal(T, "requ", k.sos.name, "Wrong name")
assert.Equal(T, "printe", k.sos.values[0], "Wrong value 0")
assert.Equal(T, "nirp", k.sos.values[1], "Wrong value 1")
assert.Equal(T, "print", k.sos.values[2], "Wrong value 2")
}

View File

@@ -97,18 +97,18 @@ const (
Stopped printerState = 5
)
// jobstate defined in rfc8011 ch 5.3.7
type jobState uint16
// // jobstate defined in rfc8011 ch 5.3.7
// type jobState uint16
const (
pending jobState = 3
pendingHeld jobState = 4
processing jobState = 5
processingStoppped jobState = 6
cancelled jobState = 7
aborted jobState = 8
completed jobState = 9
)
// const (
// pending jobState = 3
// pendingHeld jobState = 4
// processing jobState = 5
// processingStoppped jobState = 6
// cancelled jobState = 7
// aborted jobState = 8
// completed jobState = 9
// )
type statusCode uint16
@@ -128,19 +128,8 @@ func (v versionNumber) String() string {
return fmt.Sprintf("%x.%x", vn&0xff00>>8, vn&0x00ff)
}
func unmarshalSingleAttribute(byteStream io.Reader) (string, []byte) {
var length uint16
binary.Read(byteStream, binary.BigEndian, &length)
attributeName := make([]byte, length)
if length > 0 {
binary.Read(byteStream, binary.BigEndian, attributeName)
}
binary.Read(byteStream, binary.BigEndian, &length)
attributeValue := make([]byte, length)
binary.Read(byteStream, binary.BigEndian, attributeValue)
return string(attributeName), attributeValue
}
// unmarshalSingleValue reads a single key value pair from the byte stream
// RFC 8010: Attribute-with-one-value
func unmarshalSingleValue(byteStream io.Reader) (string, string) {
var length uint16
binary.Read(byteStream, binary.BigEndian, &length)
@@ -165,11 +154,52 @@ func marshalNameValue(name, value string, b []byte) {
copy(b[p:], []byte(value))
}
// func readAttribute(byteStream *bufio.Reader) (string, [][]byte) {
// var length uint16
// values := make([][]byte, 0, 1)
// binary.Read(byteStream, binary.BigEndian, &length)
// attributeName := make([]byte, length)
// if length > 0 {
// binary.Read(byteStream, binary.BigEndian, attributeName)
// }
// binary.Read(byteStream, binary.BigEndian, attributeValue)
// values = append(values, string(attributeValue))
// next, err := byteStream.Peek(1)
// if err != nil {
// panic("Failed to peek")
// }
// if next[0] != byte(keyWordValueTag) {
// // No additional values
// return string(attributeName), values
// }
// binary.Read(byteStream, binary.BigEndian, &length)
// for length > 0 {
// attributeValue := make([]byte, length)
// binary.Read(byteStream, binary.BigEndian, &length)
// attributeValue := make([]byte, length)
// if length > 0 {
// binary.Read(byteStream, binary.BigEndian, attributeValue)
// }
// values = append(values, string(attributeValue))
// next, err := byteStream.Peek(1)
// if err != nil {
// panic("Failed to peek")
// }
// if next[0] != byte(keyWordValueTag) {
// // No additional values
// return string(attributeName), values
// }
// }
// }
type Attribute interface {
Name() string
valueTag() tag
marshal() []byte
//size() int
}
type Attributes struct {
@@ -230,11 +260,10 @@ func UnMarshalAttributes(bytestream *bufio.Reader) *Attributes {
}
currentAttributeGroup := t
var lastAddValuer AddValuer
for {
err = binary.Read(bytestream, binary.BigEndian, &t)
if err != nil {
log.Fatal("End of input before end of attributes tag (%v)", err.Error())
log.Fatalf("End of input before end of attributes tag (%v)", err.Error())
}
log.Debugf("Value tag - %v", t)
switch t {
@@ -260,15 +289,10 @@ func UnMarshalAttributes(bytestream *bufio.Reader) *Attributes {
a.addAttribute(currentAttributeGroup, n)
log.Debugf("%v %v", n.name, n.value)
case keyWordValueTag:
name, value := unmarshalSingleValue(bytestream)
if name == "" {
lastAddValuer.addValue(value)
} else {
k := NewKeyWord(name, value)
a.addAttribute(currentAttributeGroup, k)
lastAddValuer = k
}
log.Debugf("%v : %v", name, value)
k := NewKeyWord("", "")
k.unmarshal(bytestream)
a.addAttribute(currentAttributeGroup, k)
log.Debugf("%v : %v", k.Name(), k.String())
case nameWithoutLanguageValueTag:
n := NewNameWithoutLanguage("", "")
n.unmarshal(bytestream)
@@ -280,45 +304,25 @@ func UnMarshalAttributes(bytestream *bufio.Reader) *Attributes {
a.addAttribute(currentAttributeGroup, attr)
log.Debugf("%v %v", attr.name, attr.value)
case mimeMediaTypeValueTag:
name, value := unmarshalSingleValue(bytestream)
if name == "" {
lastAddValuer.addValue(value)
} else {
m := NewMimeMediaType(name, value)
a.addAttribute(currentAttributeGroup, m)
lastAddValuer = m
}
log.Debugf("%v : %v", name, value)
m := NewMimeMediaType("")
m.unmarshal(bytestream)
a.addAttribute(currentAttributeGroup, m)
log.Debugf("%v : %v", m.Name(), m.String())
case integerValueTag:
name, value := unmarshalSingleInteger(bytestream)
if name == "" {
lastAddValuer.addValue(value)
} else {
i := NewInteger(name, value)
a.addAttribute(currentAttributeGroup, i)
lastAddValuer = i
}
log.Debugf("%v : %v", name, value)
i := NewInteger("")
i.unmarshal(bytestream)
a.addAttribute(currentAttributeGroup, i)
log.Debugf("%v : %v", i.name, i.values)
case rangeOfIntegerValueTag:
name, value := unmarshalSingleRangeOfInteger(bytestream)
if name == "" {
lastAddValuer.addValue(value)
} else {
r := NewRangeOfInteger(name, value)
a.addAttribute(currentAttributeGroup, r)
lastAddValuer = r
}
log.Debugf("%v : %v", name, value)
r := NewRangeOfInteger("")
r.unmarshal(bytestream)
a.addAttribute(currentAttributeGroup, r)
log.Debugf("%v : %v", r.name, r.values)
case enumValueTag:
name, value := unmarshalSingleInteger(bytestream)
if name == "" {
lastAddValuer.addValue(value)
} else {
e := NewEnum(name, value)
a.addAttribute(currentAttributeGroup, e)
lastAddValuer = e
}
log.Debugf("%v : %v", name, value)
e := NewEnum("")
e.unmarshal(bytestream)
a.addAttribute(currentAttributeGroup, e)
log.Debugf("%v : %v", e.name, e.values)
case begCollectionValueTag:
// For now just consume the collection
consumeCollection(bytestream)
@@ -326,7 +330,6 @@ func UnMarshalAttributes(bytestream *bufio.Reader) *Attributes {
attr := NewUnsupportedValue()
attr.unmarshal(bytestream)
a.addAttribute(currentAttributeGroup, attr)
case jobAttributes:
log.Debug("Start job attributes")
currentAttributeGroup = jobAttributes

View File

@@ -2,6 +2,8 @@
// SPDX-License-Identifier: BSD-3-Clause
package ipp
import "bufio"
type MimeMediaType struct {
sos *SetOfStrings
}
@@ -21,10 +23,6 @@ func (m MimeMediaType) String() string {
return m.sos.String()
}
func (m *MimeMediaType) size() int {
return m.sos.size()
}
func (m *MimeMediaType) valueTag() tag {
return m.sos.valueTag()
}
@@ -33,6 +31,10 @@ func (m *MimeMediaType) marshal() []byte {
return m.sos.marshal()
}
func (m *MimeMediaType) unmarshal(byteStream *bufio.Reader) {
m.sos.unmarshal(byteStream, mimeMediaTypeValueTag)
}
func (m *MimeMediaType) addValue(v interface{}) {
m.sos.AddValue(v.(string))
}

View File

@@ -39,13 +39,6 @@ func (n *NameWithoutLanguage) marshal() []byte {
return b
}
func (n *NameWithoutLanguage) size() int {
l := 1 + 4 // The attribute tag + 2 lengths
l += len(n.name)
l += len(n.value)
return l
}
func (n NameWithoutLanguage) Value() string {
return n.value
}

View File

@@ -41,10 +41,3 @@ func (c *NaturalLanguage) marshal() []byte {
marshalNameValue(c.name, c.value, b[1:])
return b
}
func (c *NaturalLanguage) size() int {
l := 1 + 4 // The attribute tag + 2 lengths
l += len(c.name)
l += len(c.value)
return l
}

View File

@@ -3,9 +3,9 @@
package ipp
import (
"bufio"
"encoding/binary"
"fmt"
"io"
log "github.com/sirupsen/logrus"
)
@@ -44,14 +44,44 @@ func (r *RangeOfInteger) marshal() []byte {
return []byte{}
}
func (r *RangeOfInteger) unmarshal(byteStream *bufio.Reader) error {
var length uint16
r.values = make([]IRange, 0, 1)
binary.Read(byteStream, binary.BigEndian, &length)
name := make([]byte, length)
if length > 0 {
binary.Read(byteStream, binary.BigEndian, name)
}
r.name = string(name)
binary.Read(byteStream, binary.BigEndian, &length)
if length != 8 {
return fmt.Errorf("wrong value-length of range-of-integer attribute %v", length)
}
for length > 0 {
var i IRange
err := binary.Read(byteStream, binary.BigEndian, &i.lower)
if err != nil {
return err
}
err = binary.Read(byteStream, binary.BigEndian, &i.upper)
if err != nil {
return err
}
r.values = append(r.values, i)
next, err := byteStream.Peek(3)
if err != nil {
break
}
if next[0] != byte(rangeOfIntegerValueTag) || next[1] != 0x00 || next[2] != 0x00 {
break
}
// Remove the value tag with the zero length from the stream
byteStream.Discard(3)
binary.Read(byteStream, binary.BigEndian, &length)
}
return nil
}
func (r *RangeOfInteger) addValue(v interface{}) {
r.values = append(r.values, v.(IRange))
}
func unmarshalSingleRangeOfInteger(byteStream io.Reader) (string, IRange) {
name, data := unmarshalSingleAttribute(byteStream)
var r IRange
r.lower = int32(binary.BigEndian.Uint32(data[0:4]))
r.upper = int32(binary.BigEndian.Uint32(data[4:8]))
return name, r
}

View File

@@ -3,24 +3,51 @@
package ipp
import (
"bufio"
"bytes"
"testing"
"github.com/stretchr/testify/assert"
)
func TestUnMarshalSingleRange(T *testing.T) {
func TestUnmarshalSingleRange(T *testing.T) {
testdata := []byte{
0x00, 0x04,
0x66, 0x6c, 0x6f, 0x70, //flop
0x00, 0x08,
0x00, 0x0, 0x0, 0x4, 0x00, 0x0, 0x0, 0x5,
}
b := bytes.NewBuffer(testdata)
buf := bufio.NewReader(b)
buf := bytes.NewBuffer(testdata)
var r RangeOfInteger
r.unmarshal(buf)
assert.Equal(T, "flop", r.name, "Should be equal")
assert.Equal(T, int32(4), r.values[0].lower, "Should be equal")
assert.Equal(T, int32(5), r.values[0].upper, "Should be equal")
}
func TestUnmarshalDualRanges(T *testing.T) {
testdata := []byte{
0x00, 0x04,
0x66, 0x6c, 0x6f, 0x70, //flop
0x00, 0x08,
0x00, 0x0, 0x0, 0x4, 0x00, 0x0, 0x0, 0x5,
0x33, 0x00, 0x00,
0x00, 0x08,
0x00, 0x0, 0x0, 0x6, 0x00, 0x0, 0x0, 0x9,
}
b := bytes.NewBuffer(testdata)
buf := bufio.NewReader(b)
var r RangeOfInteger
r.unmarshal(buf)
assert.Equal(T, "flop", r.name, "Should be equal")
assert.Equal(T, int32(4), r.values[0].lower, "Should be equal")
assert.Equal(T, int32(5), r.values[0].upper, "Should be equal")
assert.Equal(T, int32(6), r.values[1].lower, "Should be equal")
assert.Equal(T, int32(9), r.values[1].upper, "Should be equal")
n, v := unmarshalSingleRangeOfInteger(buf)
assert.Equal(T, "flop", n, "Should be equal")
assert.Equal(T, int32(4), v.lower, "Should be equal")
assert.Equal(T, int32(5), v.upper, "Should be equal")
}

View File

@@ -0,0 +1,56 @@
// Copyright 2021, Henrik Sölver henrik.solver@gmail.com
// SPDX-License-Identifier: BSD-3-Clause
package ipp
import (
"bufio"
"encoding/binary"
"fmt"
)
// setOfIntegers is a helper type that is used to handle integer types
// which only differs in tag value.
type setOfIntegers struct {
name string
values []int32
}
func unmarshalIntegers(byteStream *bufio.Reader, valueTag tag) (*setOfIntegers, error) {
s := new(setOfIntegers)
s.values = make([]int32, 0, 1)
var length uint16
binary.Read(byteStream, binary.BigEndian, &length)
name := make([]byte, length)
if length > 0 {
binary.Read(byteStream, binary.BigEndian, name)
}
s.name = string(name)
binary.Read(byteStream, binary.BigEndian, &length)
if length != 4 {
return nil, fmt.Errorf("wrong value-length of integer attribute %v", length)
}
var value int32 //valueBytes := make([]byte, length)
for length > 0 {
err := binary.Read(byteStream, binary.BigEndian, &value)
if err != nil {
return nil, err
}
s.values = append(s.values, value)
next, err := byteStream.Peek(3)
if err != nil {
// end of byte stream
break
}
if next[0] != byte(valueTag) || next[1] != 0x00 || next[2] != 0x00 {
// End of attribute
break
}
// Remove the value tag with the zero length from the stream
byteStream.Discard(3)
binary.Read(byteStream, binary.BigEndian, &length)
}
return s, nil
}

View File

@@ -2,7 +2,10 @@
// SPDX-License-Identifier: BSD-3-Clause
package ipp
import "encoding/binary"
import (
"bufio"
"encoding/binary"
)
// SetOfStrings is the strings attribute
type SetOfStrings struct {
@@ -32,17 +35,37 @@ func (s *SetOfStrings) valueTag() tag {
return s.vTag
}
// func (k *keyWord) unmarshal(byteStream io.Reader) {
// if len(k.values) == 0 {
// var v string
// k.name, v = unmarshalSingleValue(byteStream)
// k.values = append(k.values, v)
// } else {
// var v string
// _, v = unmarshalSingleValue(byteStream)
// k.values = append(k.values, v)
// }
// }
func (s *SetOfStrings) unmarshal(byteStream *bufio.Reader, valueTag tag) error {
var length uint16
s.vTag = valueTag
s.values = make([]string, 0, 1)
binary.Read(byteStream, binary.BigEndian, &length)
name := make([]byte, length)
if length > 0 {
binary.Read(byteStream, binary.BigEndian, name)
}
s.name = string(name)
binary.Read(byteStream, binary.BigEndian, &length)
for length > 0 {
valueBytes := make([]byte, length)
err := binary.Read(byteStream, binary.BigEndian, valueBytes)
if err != nil {
return err
}
s.values = append(s.values, string(valueBytes))
next, err := byteStream.Peek(3)
if err != nil {
break
}
if next[0] != byte(valueTag) || next[1] != 0x00 || next[2] != 0x00 {
break
}
// Remove the value tag with the zero length from the stream
byteStream.Discard(3)
binary.Read(byteStream, binary.BigEndian, &length)
}
return nil
}
func (s *SetOfStrings) marshal() []byte {
l := 5 + len(s.name) + len(s.values[0])
@@ -79,16 +102,3 @@ func (s *SetOfStrings) marshal() []byte {
func (s *SetOfStrings) AddValue(v string) {
s.values = append(s.values, v)
}
func (s *SetOfStrings) size() int {
l := 1 + 2 // The value tag (0x44) + name-length field (2 bytes)
l += len(s.name)
l += 2 // value-length field (2 bytes)
l += len(s.values[0])
// Add all additional values
for _, v := range s.values[1:] {
l += 1 + 4 // The value tag (0x44) + 2 length fields (2 bytes)
l += len(v)
}
return l
}

View File

@@ -42,10 +42,3 @@ func (c *TextWithoutLanguage) marshal() []byte {
marshalNameValue(c.name, c.value, b[1:])
return b
}
func (c *TextWithoutLanguage) size() int {
l := 1 + 4 // The attribute tag + 2 lengths
l += len(c.name)
l += len(c.value)
return l
}