Add integer attribute type.

Merges some common code between integer and enum.
Enum can now bw a set.
Add valuer must take a interface{} in addValue since it can be different types.
This commit is contained in:
2020-12-28 23:11:21 +01:00
parent e0a0c88d95
commit 1eff8711d3
7 changed files with 156 additions and 34 deletions

View File

@@ -1,23 +1,18 @@
package ipp
import (
"bytes"
"encoding/binary"
"fmt"
"io"
log "github.com/sirupsen/logrus"
)
type enum struct {
name string
value int32
name string
values []int32
}
func NewEnum(name string, value int32) *enum {
func NewEnum(name string, values ...int32) *enum {
e := new(enum)
e.name = name
e.value = value
e.values = values
return e
}
@@ -26,32 +21,21 @@ func (e enum) Name() string {
}
func (e enum) String() string {
return e.name + ":" + fmt.Sprint(e.value)
return e.name + ":" + fmt.Sprint(e.values)
}
func (e *enum) valueTag() tag {
return enumValueTag
}
func (e *enum) unmarshal(byteStream io.Reader) {
log.Warn("Unmarshal of enum is not implemented yet")
func (e *enum) size() int {
return 9 + len(e.name)
}
func (i *enum) addValue(v interface{}) {
i.values = append(i.values, v.(int32))
}
func (e *enum) marshal() []byte {
l := 3 + len(e.name) + 6
b := make([]byte, 0, l)
buf := bytes.NewBuffer(b)
buf.WriteByte(byte(enumValueTag))
binary.Write(buf, binary.BigEndian, uint16(len(e.name)))
buf.WriteString(e.name)
binary.Write(buf, binary.BigEndian, uint16(4))
binary.Write(buf, binary.BigEndian, e.value)
return buf.Bytes()
}
func (e *enum) size() int {
l := 1 + 4 // The attribute tag + 2 lengths
l += len(e.name)
l += 4
return l
return marshalInteger(enumValueTag, e.name, e.values)
}

67
packages/ipp/integer.go Normal file
View File

@@ -0,0 +1,67 @@
package ipp
import (
"bytes"
"encoding/binary"
"fmt"
"io"
)
type integer struct {
name string
values []int32
}
func NewInteger(name string, values ...int32) *integer {
e := new(integer)
e.name = name
e.values = values
return e
}
func (i integer) Name() string {
return i.name
}
func (i integer) String() string {
return i.name + ":" + fmt.Sprint(i.values)
}
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))
}
func (i *integer) marshal() []byte {
return marshalInteger(integerValueTag, i.name, i.values)
}
func marshalInteger(t tag, name string, values []int32) []byte {
l := 9 + len(name)
b := make([]byte, 0, l)
buf := bytes.NewBuffer(b)
buf.WriteByte(byte(integerValueTag))
binary.Write(buf, binary.BigEndian, uint16(len(name)))
buf.WriteString(name)
binary.Write(buf, binary.BigEndian, uint16(4))
binary.Write(buf, binary.BigEndian, values[0])
for _, v := range values[1:] {
buf.WriteByte(byte(integerValueTag))
binary.Write(buf, binary.BigEndian, uint16(0))
binary.Write(buf, binary.BigEndian, uint16(4))
binary.Write(buf, binary.BigEndian, v)
}
return buf.Bytes()
}
func unmarshalSingleInteger(byteStream io.Reader) (string, int32) {
name, data := unmarshalSingleAttribute(byteStream)
return name, int32(binary.BigEndian.Uint32(data))
}

View File

@@ -0,0 +1,38 @@
package ipp
import (
"bytes"
"testing"
"github.com/stretchr/testify/assert"
)
func TestUnMarshalSinglePositiveInteger(T *testing.T) {
testdata := []byte{
0x00, 0x04,
0x66, 0x6c, 0x6f, 0x70, //flop
0x00, 0x04,
0x00, 0x0, 0x0, 0x4,
}
buf := bytes.NewBuffer(testdata)
n, v := unmarshalSingleInteger(buf)
assert.Equal(T, "flop", n, "Should be equal")
assert.Equal(T, int32(4), v, "Should be equal")
}
func TestUnMarshalSingleNegativeInteger(T *testing.T) {
testdata := []byte{
0x00, 0x04,
0x66, 0x6c, 0x6f, 0x70, //flop
0x00, 0x04,
0xff, 0xff, 0xff, 0xfc,
}
buf := bytes.NewBuffer(testdata)
n, v := unmarshalSingleInteger(buf)
assert.Equal(T, "flop", n, "Should be equal")
assert.Equal(T, int32(-4), v, "Should be equal")
}

View File

@@ -31,7 +31,7 @@ func (k *keyWord) marshal() []byte {
return k.sos.marshal()
}
func (k *keyWord) addValue(v string) {
k.sos.AddValue(v)
func (k *keyWord) addValue(v interface{}) {
k.sos.AddValue(v.(string))
}

View File

@@ -100,6 +100,19 @@ 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
}
func unmarshalSingleValue(byteStream io.Reader) (string, string) {
var length uint16
binary.Read(byteStream, binary.BigEndian, &length)
@@ -137,7 +150,7 @@ type attributes struct {
job []Attribute
}
func (a *attributes) String() string{
func (a *attributes) String() string {
s := " OperationAttributes" + "\n"
for _, a := range a.operation {
s = s + fmt.Sprintf(" %v (%v)\n", a, a.valueTag())
@@ -231,6 +244,26 @@ func UnMarshalAttributues(body io.Reader) *attributes {
lastAddValuer = m
}
log.Debugf("%v : %v", name, value)
case integerValueTag:
name, value := unmarshalSingleInteger(body)
if name == "" {
lastAddValuer.addValue(value)
} else {
i := NewInteger(name, value)
a.addAttribute(currentAttributeGroup, i)
lastAddValuer = i
}
log.Debugf("%v : %v", name, value)
case enumValueTag:
name, value := unmarshalSingleInteger(body)
if name == "" {
lastAddValuer.addValue(value)
} else {
e := NewEnum(name, value)
a.addAttribute(currentAttributeGroup, e)
lastAddValuer = e
}
log.Debugf("%v : %v", name, value)
case jobAttributes:
log.Debug("Start job attributes")
currentAttributeGroup = jobAttributes

View File

@@ -31,6 +31,6 @@ func (m *mimeMediaType) marshal() []byte {
return m.sos.marshal()
}
func (m *mimeMediaType) addValue(v string) {
m.sos.AddValue(v)
func (m *mimeMediaType) addValue(v interface{}) {
m.sos.AddValue(v.(string))
}

View File

@@ -33,7 +33,7 @@ func (h ippMessageHeader) String() string {
}
type AddValuer interface {
addValue(string)
addValue(interface{})
}
type Request struct {