Simplify unmarshalling.
This commit is contained in:
@@ -36,9 +36,32 @@ func (b *Boolean) valueTag() tag {
|
|||||||
return booleanValueTag
|
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) {
|
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 {
|
if data[0] == 0 {
|
||||||
b.value = false
|
b.value = false
|
||||||
return
|
return
|
||||||
@@ -60,9 +83,4 @@ func (b *Boolean) marshal() []byte {
|
|||||||
buf.WriteByte(byte(0))
|
buf.WriteByte(byte(0))
|
||||||
}
|
}
|
||||||
return buf.Bytes()
|
return buf.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Boolean) size() int {
|
|
||||||
l := 5 + len(b.name)
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
@@ -45,10 +45,3 @@ func (c *CharSetValue) marshal() []byte {
|
|||||||
func (c *CharSetValue) marshalInto([]byte) int {
|
func (c *CharSetValue) marshalInto([]byte) int {
|
||||||
return 0
|
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
|
|
||||||
}
|
|
||||||
|
|||||||
94
packages/ipp/collection.hex
Normal file
94
packages/ipp/collection.hex
Normal 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}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
package ipp
|
package ipp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,10 +31,6 @@ func (e *Enum) valueTag() tag {
|
|||||||
return enumValueTag
|
return enumValueTag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Enum) size() int {
|
|
||||||
return 9 + len(e.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Enum) addValue(v interface{}) {
|
func (e *Enum) addValue(v interface{}) {
|
||||||
e.values = append(e.values, v.(int32))
|
e.values = append(e.values, v.(int32))
|
||||||
}
|
}
|
||||||
@@ -41,3 +38,11 @@ func (e *Enum) addValue(v interface{}) {
|
|||||||
func (e *Enum) marshal() []byte {
|
func (e *Enum) marshal() []byte {
|
||||||
return marshalInteger(enumValueTag, e.name, e.values)
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
package ipp
|
package ipp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Integer struct {
|
type Integer struct {
|
||||||
@@ -33,10 +33,6 @@ func (i *Integer) valueTag() tag {
|
|||||||
return integerValueTag
|
return integerValueTag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Integer) size() int {
|
|
||||||
return 9 + len(i.name) // The attribute tag + 2 lengths
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Integer) addValue(v interface{}) {
|
func (i *Integer) addValue(v interface{}) {
|
||||||
i.values = append(i.values, v.(int32))
|
i.values = append(i.values, v.(int32))
|
||||||
}
|
}
|
||||||
@@ -45,6 +41,15 @@ func (i *Integer) marshal() []byte {
|
|||||||
return marshalInteger(integerValueTag, i.name, i.values)
|
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 {
|
func marshalInteger(t tag, name string, values []int32) []byte {
|
||||||
l := 9 + len(name) + 9*(len(values)-1)
|
l := 9 + len(name) + 9*(len(values)-1)
|
||||||
b := make([]byte, 0, l)
|
b := make([]byte, 0, l)
|
||||||
@@ -62,8 +67,3 @@ func marshalInteger(t tag, name string, values []int32) []byte {
|
|||||||
}
|
}
|
||||||
return buf.Bytes()
|
return buf.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalSingleInteger(byteStream io.Reader) (string, int32) {
|
|
||||||
name, data := unmarshalSingleAttribute(byteStream)
|
|
||||||
return name, int32(binary.BigEndian.Uint32(data))
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
package ipp
|
package ipp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -18,10 +19,12 @@ func TestUnMarshalSinglePositiveInteger(T *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf := bytes.NewBuffer(testdata)
|
buf := bytes.NewBuffer(testdata)
|
||||||
|
bufbuf := bufio.NewReader(buf)
|
||||||
|
|
||||||
n, v := unmarshalSingleInteger(buf)
|
var i Integer
|
||||||
assert.Equal(T, "flop", n, "Should be equal")
|
i.unmarshal(bufbuf)
|
||||||
assert.Equal(T, int32(4), v, "Should be equal")
|
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) {
|
func TestUnMarshalSingleNegativeInteger(T *testing.T) {
|
||||||
@@ -31,10 +34,11 @@ func TestUnMarshalSingleNegativeInteger(T *testing.T) {
|
|||||||
0x00, 0x04,
|
0x00, 0x04,
|
||||||
0xff, 0xff, 0xff, 0xfc,
|
0xff, 0xff, 0xff, 0xfc,
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := bytes.NewBuffer(testdata)
|
buf := bytes.NewBuffer(testdata)
|
||||||
|
bufbuf := bufio.NewReader(buf)
|
||||||
|
|
||||||
n, v := unmarshalSingleInteger(buf)
|
var i Integer
|
||||||
assert.Equal(T, "flop", n, "Should be equal")
|
i.unmarshal(bufbuf)
|
||||||
assert.Equal(T, int32(-4), v, "Should be equal")
|
assert.Equal(T, "flop", i.name, "Should be equal")
|
||||||
|
assert.Equal(T, int32(-4), i.values[0], "Should be equal")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
package ipp
|
package ipp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
)
|
||||||
|
|
||||||
type KeyWord struct {
|
type KeyWord struct {
|
||||||
sos *SetOfStrings
|
sos *SetOfStrings
|
||||||
}
|
}
|
||||||
@@ -21,10 +25,6 @@ func (k KeyWord) String() string {
|
|||||||
return k.sos.String()
|
return k.sos.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *KeyWord) size() int {
|
|
||||||
return k.sos.size()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KeyWord) valueTag() tag {
|
func (k *KeyWord) valueTag() tag {
|
||||||
return k.sos.valueTag()
|
return k.sos.valueTag()
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,10 @@ func (k *KeyWord) marshal() []byte {
|
|||||||
return k.sos.marshal()
|
return k.sos.marshal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *KeyWord) unmarshal(byteStream *bufio.Reader) {
|
||||||
|
k.sos.unmarshal(byteStream, keyWordValueTag)
|
||||||
|
}
|
||||||
|
|
||||||
func (k *KeyWord) addValue(v interface{}) {
|
func (k *KeyWord) addValue(v interface{}) {
|
||||||
k.sos.AddValue(v.(string))
|
k.sos.AddValue(v.(string))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
package ipp
|
package ipp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -22,6 +24,28 @@ import (
|
|||||||
// assert.Equal(T, k.values[0], "printer-make-and-model")
|
// 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) {
|
func TestMarshalSimpleKeyword(T *testing.T) {
|
||||||
testdata := []byte{
|
testdata := []byte{
|
||||||
0x44, 0x00, 0x14,
|
0x44, 0x00, 0x14,
|
||||||
@@ -36,3 +60,28 @@ func TestMarshalSimpleKeyword(T *testing.T) {
|
|||||||
assert.Equal(T, testdata, m, "Should be equal")
|
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")
|
||||||
|
}
|
||||||
|
|||||||
@@ -97,18 +97,18 @@ const (
|
|||||||
Stopped printerState = 5
|
Stopped printerState = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
// jobstate defined in rfc8011 ch 5.3.7
|
// // jobstate defined in rfc8011 ch 5.3.7
|
||||||
type jobState uint16
|
// type jobState uint16
|
||||||
|
|
||||||
const (
|
// const (
|
||||||
pending jobState = 3
|
// pending jobState = 3
|
||||||
pendingHeld jobState = 4
|
// pendingHeld jobState = 4
|
||||||
processing jobState = 5
|
// processing jobState = 5
|
||||||
processingStoppped jobState = 6
|
// processingStoppped jobState = 6
|
||||||
cancelled jobState = 7
|
// cancelled jobState = 7
|
||||||
aborted jobState = 8
|
// aborted jobState = 8
|
||||||
completed jobState = 9
|
// completed jobState = 9
|
||||||
)
|
// )
|
||||||
|
|
||||||
type statusCode uint16
|
type statusCode uint16
|
||||||
|
|
||||||
@@ -128,19 +128,8 @@ func (v versionNumber) String() string {
|
|||||||
return fmt.Sprintf("%x.%x", vn&0xff00>>8, vn&0x00ff)
|
return fmt.Sprintf("%x.%x", vn&0xff00>>8, vn&0x00ff)
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalSingleAttribute(byteStream io.Reader) (string, []byte) {
|
// unmarshalSingleValue reads a single key value pair from the byte stream
|
||||||
var length uint16
|
// RFC 8010: Attribute-with-one-value
|
||||||
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 unmarshalSingleValue(byteStream io.Reader) (string, string) {
|
func unmarshalSingleValue(byteStream io.Reader) (string, string) {
|
||||||
var length uint16
|
var length uint16
|
||||||
binary.Read(byteStream, binary.BigEndian, &length)
|
binary.Read(byteStream, binary.BigEndian, &length)
|
||||||
@@ -165,11 +154,52 @@ func marshalNameValue(name, value string, b []byte) {
|
|||||||
copy(b[p:], []byte(value))
|
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 {
|
type Attribute interface {
|
||||||
Name() string
|
Name() string
|
||||||
valueTag() tag
|
valueTag() tag
|
||||||
marshal() []byte
|
marshal() []byte
|
||||||
//size() int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Attributes struct {
|
type Attributes struct {
|
||||||
@@ -230,11 +260,10 @@ func UnMarshalAttributes(bytestream *bufio.Reader) *Attributes {
|
|||||||
}
|
}
|
||||||
currentAttributeGroup := t
|
currentAttributeGroup := t
|
||||||
|
|
||||||
var lastAddValuer AddValuer
|
|
||||||
for {
|
for {
|
||||||
err = binary.Read(bytestream, binary.BigEndian, &t)
|
err = binary.Read(bytestream, binary.BigEndian, &t)
|
||||||
if err != nil {
|
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)
|
log.Debugf("Value tag - %v", t)
|
||||||
switch t {
|
switch t {
|
||||||
@@ -260,15 +289,10 @@ func UnMarshalAttributes(bytestream *bufio.Reader) *Attributes {
|
|||||||
a.addAttribute(currentAttributeGroup, n)
|
a.addAttribute(currentAttributeGroup, n)
|
||||||
log.Debugf("%v %v", n.name, n.value)
|
log.Debugf("%v %v", n.name, n.value)
|
||||||
case keyWordValueTag:
|
case keyWordValueTag:
|
||||||
name, value := unmarshalSingleValue(bytestream)
|
k := NewKeyWord("", "")
|
||||||
if name == "" {
|
k.unmarshal(bytestream)
|
||||||
lastAddValuer.addValue(value)
|
a.addAttribute(currentAttributeGroup, k)
|
||||||
} else {
|
log.Debugf("%v : %v", k.Name(), k.String())
|
||||||
k := NewKeyWord(name, value)
|
|
||||||
a.addAttribute(currentAttributeGroup, k)
|
|
||||||
lastAddValuer = k
|
|
||||||
}
|
|
||||||
log.Debugf("%v : %v", name, value)
|
|
||||||
case nameWithoutLanguageValueTag:
|
case nameWithoutLanguageValueTag:
|
||||||
n := NewNameWithoutLanguage("", "")
|
n := NewNameWithoutLanguage("", "")
|
||||||
n.unmarshal(bytestream)
|
n.unmarshal(bytestream)
|
||||||
@@ -280,45 +304,25 @@ func UnMarshalAttributes(bytestream *bufio.Reader) *Attributes {
|
|||||||
a.addAttribute(currentAttributeGroup, attr)
|
a.addAttribute(currentAttributeGroup, attr)
|
||||||
log.Debugf("%v %v", attr.name, attr.value)
|
log.Debugf("%v %v", attr.name, attr.value)
|
||||||
case mimeMediaTypeValueTag:
|
case mimeMediaTypeValueTag:
|
||||||
name, value := unmarshalSingleValue(bytestream)
|
m := NewMimeMediaType("")
|
||||||
if name == "" {
|
m.unmarshal(bytestream)
|
||||||
lastAddValuer.addValue(value)
|
a.addAttribute(currentAttributeGroup, m)
|
||||||
} else {
|
log.Debugf("%v : %v", m.Name(), m.String())
|
||||||
m := NewMimeMediaType(name, value)
|
|
||||||
a.addAttribute(currentAttributeGroup, m)
|
|
||||||
lastAddValuer = m
|
|
||||||
}
|
|
||||||
log.Debugf("%v : %v", name, value)
|
|
||||||
case integerValueTag:
|
case integerValueTag:
|
||||||
name, value := unmarshalSingleInteger(bytestream)
|
i := NewInteger("")
|
||||||
if name == "" {
|
i.unmarshal(bytestream)
|
||||||
lastAddValuer.addValue(value)
|
a.addAttribute(currentAttributeGroup, i)
|
||||||
} else {
|
log.Debugf("%v : %v", i.name, i.values)
|
||||||
i := NewInteger(name, value)
|
|
||||||
a.addAttribute(currentAttributeGroup, i)
|
|
||||||
lastAddValuer = i
|
|
||||||
}
|
|
||||||
log.Debugf("%v : %v", name, value)
|
|
||||||
case rangeOfIntegerValueTag:
|
case rangeOfIntegerValueTag:
|
||||||
name, value := unmarshalSingleRangeOfInteger(bytestream)
|
r := NewRangeOfInteger("")
|
||||||
if name == "" {
|
r.unmarshal(bytestream)
|
||||||
lastAddValuer.addValue(value)
|
a.addAttribute(currentAttributeGroup, r)
|
||||||
} else {
|
log.Debugf("%v : %v", r.name, r.values)
|
||||||
r := NewRangeOfInteger(name, value)
|
|
||||||
a.addAttribute(currentAttributeGroup, r)
|
|
||||||
lastAddValuer = r
|
|
||||||
}
|
|
||||||
log.Debugf("%v : %v", name, value)
|
|
||||||
case enumValueTag:
|
case enumValueTag:
|
||||||
name, value := unmarshalSingleInteger(bytestream)
|
e := NewEnum("")
|
||||||
if name == "" {
|
e.unmarshal(bytestream)
|
||||||
lastAddValuer.addValue(value)
|
a.addAttribute(currentAttributeGroup, e)
|
||||||
} else {
|
log.Debugf("%v : %v", e.name, e.values)
|
||||||
e := NewEnum(name, value)
|
|
||||||
a.addAttribute(currentAttributeGroup, e)
|
|
||||||
lastAddValuer = e
|
|
||||||
}
|
|
||||||
log.Debugf("%v : %v", name, value)
|
|
||||||
case begCollectionValueTag:
|
case begCollectionValueTag:
|
||||||
// For now just consume the collection
|
// For now just consume the collection
|
||||||
consumeCollection(bytestream)
|
consumeCollection(bytestream)
|
||||||
@@ -326,7 +330,6 @@ func UnMarshalAttributes(bytestream *bufio.Reader) *Attributes {
|
|||||||
attr := NewUnsupportedValue()
|
attr := NewUnsupportedValue()
|
||||||
attr.unmarshal(bytestream)
|
attr.unmarshal(bytestream)
|
||||||
a.addAttribute(currentAttributeGroup, attr)
|
a.addAttribute(currentAttributeGroup, attr)
|
||||||
|
|
||||||
case jobAttributes:
|
case jobAttributes:
|
||||||
log.Debug("Start job attributes")
|
log.Debug("Start job attributes")
|
||||||
currentAttributeGroup = jobAttributes
|
currentAttributeGroup = jobAttributes
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
package ipp
|
package ipp
|
||||||
|
|
||||||
|
import "bufio"
|
||||||
|
|
||||||
type MimeMediaType struct {
|
type MimeMediaType struct {
|
||||||
sos *SetOfStrings
|
sos *SetOfStrings
|
||||||
}
|
}
|
||||||
@@ -21,10 +23,6 @@ func (m MimeMediaType) String() string {
|
|||||||
return m.sos.String()
|
return m.sos.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MimeMediaType) size() int {
|
|
||||||
return m.sos.size()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MimeMediaType) valueTag() tag {
|
func (m *MimeMediaType) valueTag() tag {
|
||||||
return m.sos.valueTag()
|
return m.sos.valueTag()
|
||||||
}
|
}
|
||||||
@@ -33,6 +31,10 @@ func (m *MimeMediaType) marshal() []byte {
|
|||||||
return m.sos.marshal()
|
return m.sos.marshal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MimeMediaType) unmarshal(byteStream *bufio.Reader) {
|
||||||
|
m.sos.unmarshal(byteStream, mimeMediaTypeValueTag)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MimeMediaType) addValue(v interface{}) {
|
func (m *MimeMediaType) addValue(v interface{}) {
|
||||||
m.sos.AddValue(v.(string))
|
m.sos.AddValue(v.(string))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,13 +39,6 @@ func (n *NameWithoutLanguage) marshal() []byte {
|
|||||||
return b
|
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 {
|
func (n NameWithoutLanguage) Value() string {
|
||||||
return n.value
|
return n.value
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,10 +41,3 @@ func (c *NaturalLanguage) marshal() []byte {
|
|||||||
marshalNameValue(c.name, c.value, b[1:])
|
marshalNameValue(c.name, c.value, b[1:])
|
||||||
return b
|
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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
package ipp
|
package ipp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@@ -44,14 +44,44 @@ func (r *RangeOfInteger) marshal() []byte {
|
|||||||
return []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{}) {
|
func (r *RangeOfInteger) addValue(v interface{}) {
|
||||||
r.values = append(r.values, v.(IRange))
|
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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,24 +3,51 @@
|
|||||||
package ipp
|
package ipp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUnMarshalSingleRange(T *testing.T) {
|
func TestUnmarshalSingleRange(T *testing.T) {
|
||||||
testdata := []byte{
|
testdata := []byte{
|
||||||
0x00, 0x04,
|
0x00, 0x04,
|
||||||
0x66, 0x6c, 0x6f, 0x70, //flop
|
0x66, 0x6c, 0x6f, 0x70, //flop
|
||||||
0x00, 0x08,
|
0x00, 0x08,
|
||||||
0x00, 0x0, 0x0, 0x4, 0x00, 0x0, 0x0, 0x5,
|
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")
|
|
||||||
}
|
}
|
||||||
|
|||||||
56
packages/ipp/setofintegers.go
Normal file
56
packages/ipp/setofintegers.go
Normal 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
|
||||||
|
}
|
||||||
@@ -2,7 +2,10 @@
|
|||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
package ipp
|
package ipp
|
||||||
|
|
||||||
import "encoding/binary"
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
// SetOfStrings is the strings attribute
|
// SetOfStrings is the strings attribute
|
||||||
type SetOfStrings struct {
|
type SetOfStrings struct {
|
||||||
@@ -32,17 +35,37 @@ func (s *SetOfStrings) valueTag() tag {
|
|||||||
return s.vTag
|
return s.vTag
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (k *keyWord) unmarshal(byteStream io.Reader) {
|
func (s *SetOfStrings) unmarshal(byteStream *bufio.Reader, valueTag tag) error {
|
||||||
// if len(k.values) == 0 {
|
var length uint16
|
||||||
// var v string
|
s.vTag = valueTag
|
||||||
// k.name, v = unmarshalSingleValue(byteStream)
|
s.values = make([]string, 0, 1)
|
||||||
// k.values = append(k.values, v)
|
binary.Read(byteStream, binary.BigEndian, &length)
|
||||||
// } else {
|
name := make([]byte, length)
|
||||||
// var v string
|
if length > 0 {
|
||||||
// _, v = unmarshalSingleValue(byteStream)
|
binary.Read(byteStream, binary.BigEndian, name)
|
||||||
// k.values = append(k.values, v)
|
}
|
||||||
// }
|
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 {
|
func (s *SetOfStrings) marshal() []byte {
|
||||||
l := 5 + len(s.name) + len(s.values[0])
|
l := 5 + len(s.name) + len(s.values[0])
|
||||||
@@ -79,16 +102,3 @@ func (s *SetOfStrings) marshal() []byte {
|
|||||||
func (s *SetOfStrings) AddValue(v string) {
|
func (s *SetOfStrings) AddValue(v string) {
|
||||||
s.values = append(s.values, v)
|
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
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -42,10 +42,3 @@ func (c *TextWithoutLanguage) marshal() []byte {
|
|||||||
marshalNameValue(c.name, c.value, b[1:])
|
marshalNameValue(c.name, c.value, b[1:])
|
||||||
return b
|
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
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user