"General IE based message handling" Object subclass: IEBase [ type [ "Go through the elementId of the class" ^ self class elementId ] writeOnDirect: aMsg [ "This should be implemented by the subclass" self subclassResponsibility ] writeOn: aMsg [ aMsg putByte: self class elementId. self writeOnDirect: aMsg. ] ] Object subclass: IEMessage [ | ies type | IEMessage class >> initWith: type [ ^ (self new) type: type; yourself ] IEMessage class >> findIE: type with: data from: aIEBase [ "TODO: This needs to move some basic dispatch class" "Find the IE that handles the type specified" aIEBase allSubclassesDo: [:each | each elementId = type ifTrue: [ ^ each parseFrom: data. ]. ]. ^ Exception signal: 'Unsupported IE type: ', type asString. ] IEMessage class >> decode: aByteArray with: aIEBase [ | msg dat | msg := IEMessage initWith: (aByteArray at: 1). dat := aByteArray copyFrom: 2. [dat isEmpty not] whileTrue: [ | type size data | type := dat at: 1. size := dat at: 2. data := dat copyFrom: 1 to: 2 + size. dat := dat copyFrom: 3 + size. msg addIe: (self findIE: type with: data from: aIEBase). ]. ^ msg ] type: aType [ type := aType. ] type [ ^ type ] addIe: aIe [ self ies add: aIe. ] ies [ ies isNil ifTrue: [ ies := OrderedCollection new. ]. ^ ies ] findIE: type ifAbsent: block [ "Find the IE with the type" self ies do: [:each | each type = type ifTrue: [ ^ each ]. ]. ^ block value. ] findIE: type ifPresent: block [ "Find the IE with the type" self ies do: [:each | each type = type ifTrue: [ ^ block value: each ]. ]. ^ nil. ] writeOn: aMsg [ aMsg putByte: type. self ies do: [:each | each writeOn: aMsg ] ] ] Object subclass: BCD [ BCD class >> encode: aNumber [ | col num | col := OrderedCollection new. num := aNumber. 1 to: 3 do: [:each | col add: num \\ 10. num := num // 10. ]. ^ col reverse asByteArray ] BCD class >> decode: aByteArray [ | num cum | num := 0. cum := 1. aByteArray size to: 1 by: -1 do: [:each | | at | num := num + ((aByteArray at: each) * cum). cum := cum * 10. ]. ^ num ] ]