• @Choice decorator match a value to a record of value:primitive.

    The @Choice decorator is just syntactic sugar to the @IfThen decorator, useful for simple straightforward equality comparaison that doesn't requires any preprocessing.

    Type Parameters

    • This extends object

      The type of the class the decorator is applied to.

    • Value

      The type of the decorated property.

    • Args extends string

    Parameters

    • cmp: StringFormattedRecursiveKeyOf<This, Args> | ((targetInstance: This) => any)

      The name of the property of the target instance containing a value or a function receiving the target instance as parameter that return the value to compare to the record param.

    • match: Record<any, undefined | Primitive<any> | [Primitive<any>, RelationParameters<This, Args>]>

      A record where keys are compared against the evaluated cmp value, and values define the corresponding relations.

    • Optionalargs: RelationParameters<This, Args>

      The arguments to pass to the matching relation definition (see Primitive.RelationParameters)

    Returns DecoratorType<This, Value>

    The property decorator function.

    The simplest way to use the @Choice decorator is to reference the name of a property belonging to the target instance to match with the record.

    class Chunk {
    @Relation(PrimitiveSymbol.u8)
    type: number

    @Choice('type', {
    0x01: PrimitiveSymbol.u8,
    0x02: PrimitiveSymbol.u16,
    0x03: undefined,
    })
    data: number
    }

    class Protocol {
    @While((value: Chunk) => value.type !== 0x03)
    message: Chunk[]
    }

    You can also pass arguments to the relation using comma separeted string. In the following example the value of the property 'length' and 'type' is passed to the constructor of 'Data' on creation. Notice that relation you want to pass arguments requires to be defined inside of an array of two member.

    class Data {
    _length: number
    _type: number

    @Count('_length')
    @Relation(PrimitiveSymbol.u8)
    data: number[]

    ...

    constructor(length: number, type: number) {
    this._length = length
    this._type = type
    }
    }

    class Header {
    @Count(4)
    @Relation(PrimitiveSymbol.u8)
    magic: number

    @Relation(PrimitiveSymbol.u32)
    crc: number
    }

    class Protocol {
    @Relation(PrimitiveSymbol.u32)
    length: number

    @Relation(PrimitiveSymbol.u8)
    type: number

    @Choice('type', {
    0x01: Header,
    0x02: [Data, 'length, type'],
    0x03: undefined,
    })
    data: Header | Data | undefined
    }

    An alternative to string reference is to use functions if you need to performs manipulation on the datas.

    class Protocol {
    @Relation(PrimitiveSymbol.u32)
    length: number

    @Relation(PrimitiveSymbol.u8)
    type: number

    @Choice(_ => _.type, {
    0x01: Header,
    0x02: [Data, (instance: BinProtocol) => [instance.length - 5, instance.type]],
    0x03: undefined,
    })
    data: number
    }

    You can also define the default arguments you pass to every relations. In the following example the value of the property 'length' will be passed to every relation on creation.

    class Protocol {
    @Relation(PrimitiveSymbol.u32)
    length: number

    @Relation(PrimitiveSymbol.u8)
    type: number

    @Choice('type', {
    0x01: Header,
    0x02: Data,
    0x03: undefined,
    }, 'length')
    data: number
    }

    Use @Choice with the @Else decorator to pass a Primitive by default (see Else)

    class Protocol {
    @Relation(PrimitiveSymbol.u8)
    something: number

    @Choice('something', {
    0x01: PrimitiveSymbol.u8
    })
    @Else(PrimitiveSymbol.u16)
    data: number
    }